Search code examples
cmemory-leaksvalgrindstrdup

Valgrind gives error memory "still reachable"


I am having the following error when I run Valgrind, I tried to free all the used functions, but still have the same error message

==303912== HEAP SUMMARY:
==303912==     in use at exit: 348 bytes in 2 blocks
==303912==   total heap usage: 1,192 allocs, 1,190 frees, 153,918 bytes allocated
==303912== 
==303912== 348 bytes in 2 blocks are still reachable in loss record 1 of 1
==303912==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==303912==    by 0x490050E: strdup (strdup.c:42)
==303912==    by 0x109B8E: main (minishell.c:178)
==303912== 
==303912== LEAK SUMMARY:
==303912==    definitely lost: 0 bytes in 0 blocks
==303912==    indirectly lost: 0 bytes in 0 blocks
==303912==      possibly lost: 0 bytes in 0 blocks
**==303912==    still reachable: 348 bytes in 2 blocks**
==303912==         suppressed: 0 bytes in 0 blocks
==303912== 
==303912== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Line 42 in valgrind error message refers to "signal_value = 1", not sure why?!:

sigjmp_buf jmpbuf;
volatile sig_atomic_t signal_value= false;

void catch_signal(int sign) {
    if (!signal_value) {
        write(STDOUT_FILENO, "\n", 1);
        siglongjmp(jmpbuf, 1);
        signal_value = 1;
    }
    else{
        signal_value = 0;
        printf("\n");
    }
}

and line 178 here is right at "argvals[num_tokens] = strdup(token);" the second part where it is referring to in valgrind

        while(token!=NULL) {
            argvals[num_tokens] = strdup(token);
            num_tokens++;
            token = strtok(NULL, " ");
        }
        if (num_tokens == 0) {
            continue;
        } if (strcmp(argvals[0], "exit") == 0) {
            for (int j = 0; j < num_tokens; j++) {
                        free((char*)argvals[j]);
            }
            return EXIT_SUCCESS;
        } 

Solution

  • The line of Valgrind output that should concern you is this specific one:

    ==303912==    by 0x109B8E: main (minishell.c:178)
    

    Other lines above it are referring to code inside library functions, which you do not have control over. They are just automatically shown by Valgrind as part of the stack trace.

    Memory marked by Valgrind as "still reachable" is memory that is:

    1. Allocated by your program at some point.
    2. Not freed before the program exit.
    3. Still pointed to by some variable at program exit (this is what "reachable" means).

    Valgrind tells you that your call to strdup() allocated some memory that you never freed, but this is not a real error or a problem. You could in theory free() said memory just before returning from main, but it isn't really needed, as the operating system will clear the entire memory space of your program on exit. If you need some memory allocated until the end of your program, you can avoid "wasting time" freeing it. This is why Valgrind tells you about it, but does not actually report it as an error.

    If you instead don't need that allocated memory until the very end of your program, you should free it as soon as it is not needed anymore. Valgrind can't really know whether this is the case though, it's your call as the programmer to understand it.