Weird issue with C

In this forum members can discuss topics about specific programming languages.
Post Reply
User avatar
PurpleBlu3s
Posts: 73
Joined: Mon Sep 19, 2011 5:49 pm

Weird issue with C

Post by PurpleBlu3s » Thu Jun 28, 2012 1:49 pm

I don't if anyone has ever seen anything like this before, but basically, I was doing one of the problems in C, with an array of primes, primes[0] = 2, primes[1] = 3, primes[2] = 5, ...

After I initially set up the array, I confirmed that primes[1] == 3, however, inside a function, called later, primes[1] was suddenly 2! I NEVER assigned any value of primes at any point after the initial assignments. Even weirder, when I did printf("%d\n", primes[1]) in the main function inside the loop that was calling the function that seemed to be affecting primes[1], it suddenly stopped happening, and the behaviour of the program was as expected!

I would show the code, but I can't because it's for Problem 179. If anyone has solved that, and wants to see however, I will show it.

I could somehow be missing something here, but surely ONLY adding that printf statement should not change the behaviour of the program (beyond writing a line to stdout).

Seems like quantum behaviour. :P

Anyone have a clue what this could be?

Thanks.
Image

thundre
Posts: 356
Joined: Sun Mar 27, 2011 9:01 am

Re: Weird issue with C

Post by thundre » Thu Jun 28, 2012 4:27 pm

Assuming that the array is declared static so only one instance is expected...

Something in your code is writing to a pointer-based location that overlaps your primes array.

Adding code can shift things around so that you're overwriting a different variable or a different part of the array. But there's still a bug.

If you post only the lines of code that (1) declare and (2) allocate memory for the array, it won't spoil the problem. I have already solved it, but I haven't used C in years so you'll have better luck in the forum.
Image

brainiac1530
Posts: 16
Joined: Sun Mar 02, 2014 2:32 pm

Re: Weird issue with C

Post by brainiac1530 » Sun Mar 02, 2014 3:15 pm

This is one of the reasons I hate C-style arrays. Functions receive arrays as pointer variables. So it is possible for the function to receive a pointer to a different location than the initial position, or for that pointer to get incremented so that it points to the next position. This is probably what happened.

Etamin
Posts: 1
Joined: Thu Jul 17, 2014 12:11 am

Re: Weird issue with C

Post by Etamin » Thu Jul 17, 2014 12:28 am

Actually I'm pretty sure arrays in C are just constant pointers to the first element, so you can't receive a pointer to a location other than the initial location unless you pass the pointer in an arithmetic expression e.g.

Code: Select all

//compiles
//void subroutine(int*);

int array[5] = { 1, 2, 3, 4, 5 };
subroutine(array + 100); 

Code: Select all

//None of these expressions compile
array++;
++array;
array += 100;
array = array + 5;
Also if you're worried about accidentally incrementing the function argument pointer somehow, just pass it as const.

Code: Select all

void subroutine(int * const array)

JopieBK
Posts: 6
Joined: Tue Jun 24, 2014 12:40 pm

Re: Weird issue with C

Post by JopieBK » Wed Jul 30, 2014 12:54 pm

Arrays aren't pointers to the any element, constant or otherwise. See here and But I heard that char a[] was identical to char *a. In your 'subroutine(array + 100)' example the compiler is creating a pointer to the first element of array and then adding 100 to that new pointer.

The compiler treats pointers and arrays differently when it generates code, but most people only see the written code and the output behaviour, not the assembly in between. In some cases that resulting behaviour looks consistent with the idea that an array is a constant pointer and the belief occurs that it's safe or correct to think of arrays as being pointers. This almost always eventually results in confusion and trouble when meeting those situations where arrays don't behave in a similar fashion to pointers, especially when trying to use multidimensional arrays.

User avatar
ggoyo
Posts: 25
Joined: Sun Jun 22, 2014 9:45 am
Location: Paris
Contact:

Re: Weird issue with C

Post by ggoyo » Thu Jul 31, 2014 6:01 pm

I think the problem is scope. You are probably calling a different variable inside the function but think it's the same because it has the same name. But I might be totally wrong since we can't see the code.

If it gives weird results in main after you called the function then it could be what thundre said.
thundre wrote:Something in your code is writing to a pointer-based location that overlaps your primes array.
JopieBK wrote:Arrays aren't pointers to the any element, constant or otherwise.
If you do printf("%p",a); where a is an array, you would surprisingly find the same thing as printf("%p",&a[0]) which is exactly what Etamin said.
Image

juris.c
Posts: 23
Joined: Sat Oct 24, 2009 10:18 am

Re: Weird issue with C

Post by juris.c » Sat Aug 30, 2014 5:42 pm

Subject is appropriate for this question so I put it here.
Consider the following C code. Program itself have no sense, but I don't understand why not all data is written to file? On my computer (Win 7) only 1 999 424 bytes is written but it must be 2 000 000.

Code: Select all

#include <stdio.h>
#include <stdlib.h>

typedef unsigned long long ULL;
typedef unsigned char BYTE;

const ULL LIMIT=1000000;

BYTE *my_array;
ULL i;
FILE *pf;

int main(void)
{
  my_array = malloc((LIMIT+1)*sizeof(BYTE));
    if (!my_array)
      {
        printf("Unable to allocate memory!");
        exit(EXIT_FAILURE);
      }
  for (i=0; i<=LIMIT; i++) my_array[i] = 0;

  pf = fopen("D:\\my_data.bin","wb+");
  fwrite(&my_array[1],sizeof(BYTE),LIMIT,pf);
  fseek(pf,0,SEEK_SET);
  fread(&my_array[1],sizeof(BYTE),LIMIT,pf);
  fwrite(&my_array[1],sizeof(BYTE),LIMIT,pf);
  free(my_array);
  fclose(pf);
  return 0;
}

User avatar
hk
Administrator
Posts: 10075
Joined: Sun Mar 26, 2006 9:34 am
Location: Haren, Netherlands

Re: Weird issue with C

Post by hk » Sat Aug 30, 2014 7:08 pm

Shouldn't you close the file before freeing it?
In my programming language (Delphi) the use of the close statement is just writing remaining bytes to the file that are still in the buffer.
Image

juris.c
Posts: 23
Joined: Sat Oct 24, 2009 10:18 am

Re: Weird issue with C

Post by juris.c » Sat Aug 30, 2014 8:10 pm

Unfortunately that doesn't help.

User avatar
mpiotte
Administrator
Posts: 1914
Joined: Tue May 08, 2012 4:40 pm
Location: Montréal, Canada

Re: Weird issue with C

Post by mpiotte » Sat Aug 30, 2014 8:16 pm

I'm not positive fseek() flushes the write buffer. Maybe you need to fflush() before calling fseek().
Image

juris.c
Posts: 23
Joined: Sat Oct 24, 2009 10:18 am

Re: Weird issue with C

Post by juris.c » Sat Aug 30, 2014 9:13 pm

Do you mean fflush(pf) or fflush(NULL)?! Anyway none of these help too. I tried to put before every fseek(), fread() and fwrite().

JopieBK
Posts: 6
Joined: Tue Jun 24, 2014 12:40 pm

Re: Weird issue with C

Post by JopieBK » Tue Sep 02, 2014 1:36 pm

juris.c wrote:Consider the following C code. Program itself have no sense, but I don't understand why not all data is written to file? On my computer (Win 7) only 1 999 424 bytes is written but it must be 2 000 000.
Long answer
If you experiment a little with different values of LIMIT and checking the return value of fwrite, you'll find that for some values the program behaves as expected, for some it writes different amounts to that expected and for others it writes nothing at all. You should also find that if you omit the fseek and fread lines it also behaves as expected. And if you were to be explicit about a buffer using setbuf, it'll behave differently in some situations (though still not as expected). All this points towards buffer issues created during the switch between fread and fwrite.

The exact cause and effect of those issues is compiler-and-platform dependent, but isn't 'wrong' because it isn't behaviour outside of the standard. (Did you notice that the 999424 bytes written by the second fwrite call is an exact multiple of 4096...? If you set LIMIT to 1003520 - a multiple of 4096 - it works fine, if you set LIMIT to 1003519 it still only writes 1003519+999424 bytes to the file.)

The ANSI standard states that when using a '+' stream (one configured for both input and output) fflush or fseek should be used when switching between read and write operations. The GNU library claims not to have this need, but I certainly get it using GCC on Win7. fflush doesn't help, but fseek does.

Short answer
Placing

Code: Select all

fseek(pf,0,SEEK_CUR);
after the fread line causes the program to write 2 x LIMIT as expected.

Post Reply