Search code examples
cvalgrindrealloc

Program with realloc behave differently in Valgrind


I wrote a function to read a string with fgets that uses realloc() to make the buffer grow when needed:

char * read_string(char * message){
    printf("%s", message);
    size_t buffsize = MIN_BUFFER;
    char *buffer = malloc(buffsize);
    if (buffer == NULL) return NULL;
    char *p;
    for(p = buffer ; (*p = getchar()) != '\n' && *p != EOF ; ++p)
        if (p - buffer == buffsize - 1) {
            buffer = realloc(buffer, buffsize *= 2) ;
            if (buffer == NULL) return NULL;
        }
    *p = 0;
    p = malloc(p - buffer + 1);
    if (p == NULL) return NULL;
    strcpy(p, buffer);
    free(buffer);
    return p;
}

I compiled the program and tried it, and it worked like expected. But when I run it with valgrind, the function returns NULL when the read string is >= MIN_BUFFER and valgrind says:

(...)
==18076==  Invalid write of size 1
==18076==    at 0x8048895: read_string (programme.c:73)
==18076==    by 0x804898E: main (programme.c:96)
==18076==  Address 0x41fc02f is 0 bytes after a block of size 7 free'd
==18076==    at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18076==    by 0x8048860: read_string (programme.c:76)
(...)
==18076== Warning: silly arg (-48) to malloc()
(...)

I added a printf statement between *p=0; and p=malloc... and it confirmed that the arg passed had a value of -48. I didn't know that programs don't run the same way when launched alone and with valgrind. Is there something wrong in my code or is it just a valgrind bug?


Solution

  • When you realloc the buffer, your pointer 'p' still points at the old buffer.

    That will stomp memory, and also cause future allocations to use bogus values.