2

I've stared at this so long that it's all starting to run together.
So I'm getting a valgrind error:

==25468== Invalid write of size 4
==25468==    at 0x52CF64D: _IO_vfscanf (vfscanf.c:1857)
==25468==    by 0x52D730A: __isoc99_fscanf (isoc99_fscanf.c:35)
==25468==    by 0x402DDB: loadMindRAW (gplib.c:172)
==25468==    by 0x4047EE: loadAgent (gplib.c:739)
==25468==    by 0x4048BD: loadAgentsFromFile (gplib.c:799)
==25468==    by 0x4010C3: initRound (gpfight.c:220)
==25468==    by 0x400EBE: main (gpfight.c:99)
==25468==  Address 0x584388d is 253 bytes inside a block of size 256 alloc'd
==25468==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

And here's the offender:

void loadMindRAW(FILE* f_file, unsigned char* mind)
{
    int i;
    for(i=0; i < MIND_SIZE; i++)
    {
        fscanf(f_file,"%d,",&(mind[i]));
    }
}

The incoming unsigned character array was malloced just prior: (MIND_SIZE is 256)

tmpAgent->mind = malloc(MIND_SIZE*sizeof(unsigned char));
loadMindRAW(f_file, tmpAgent->mind);

Am I pointing to my mind's addresses correctly? &(mind[i]) seemed a little kludgy. Raw pointer manipulation, mind+i has the same behavior. Am I missing something simple here?

Philip
  • 1,539
  • 14
  • 23

1 Answers1

4

You are pointing to the address correctly, but you may not pass a pointer to unsigned char to fscanf in a position expecting an int pointer. This is because fscanf sees %d specifier, it assumes that the corresponding position in the variadic argument list is a pointer to signed int; because of the way the varargs are implemented in C and C++, fscanf has no other way of going about it.

Here is how you should rewrite your loop:

for(i=0; i < MIND_SIZE; i++)
{
    int tmp;
    fscanf(f_file,"%d,",&tmp);
    mind[i] = (unsigned char)tmp;
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • And there you are. Like a BOSS. Thank you. I was staring at that for two hours. AHHHHH, that explains why it was size 4. – Philip May 20 '12 at 19:37
  • An alternative option in C99 and C11 is to specify byte-size integers in the `fscanf()` format: `"%hhd,"`, which would allow you to avoid the `tmp` variable. – Jonathan Leffler May 20 '12 at 19:52