Still reachable with puts and printf

2019-07-15 11:39发布

问题:

Valgrind is reporting the still reachable "error" on functions like printf and puts. I really don't know what to do about this. I need to get rid of it since it's a school project and there has to be no errors at all. How do I deal with this? From the report I can see those functions use malloc, but I always thought they handled the memory by themselves, right? I'm using mac OS X so maybe it's a problem between valgrind and the OS?

SAMPLE CODE: The error appears on any of the puts or printf that are used

void twittear(array_t* array_tweets, hash_t* hash, queue_t* queue_input){

    char* user = queue_see_first(queue_input);
    char key[1] = "@";

    if (!user || user[0] != key[0]) {
        puts("ERROR_WRONG_COMAND");
        return;
    }

    queue_t* queue_keys = queue_create();
    char* text = join_text(queue_input, queue_keys);

    if (!text) {
        puts("ERROR_TWEET_TOO_LONG");
            queue_destroy(queue_keys, NULL);
        return;
    }

    int id = new_tweet(array_tweets, text);
    while (!queue_is_empty(queue_keys))
        hash_tweet(hash, queue_dequeue(queue_keys), id);
    queue_destroy(queue_keys, NULL);
    printf("OK %d\n", id);
}

ERROR:

==1954== 16,384 bytes in 1 blocks are still reachable in loss record 77 of 77
==1954==    at 0x47E1: malloc (vg_replace_malloc.c:300)
==1954==    by 0x183855: __smakebuf (in /usr/lib/system/libsystem_c.dylib)
==1954==    by 0x198217: __swsetup (in /usr/lib/system/libsystem_c.dylib)
==1954==    by 0x1B1158: __v2printf (in /usr/lib/system/libsystem_c.dylib)
==1954==    by 0x1B16AF: __xvprintf (in /usr/lib/system/libsystem_c.dylib)
==1954==    by 0x188B29: vfprintf_l (in /usr/lib/system/libsystem_c.dylib)
==1954==    by 0x18696F: printf (in /usr/lib/system/libsystem_c.dylib)
==1954==    by 0x1000036F3: twittear (main.c:138)
==1954==    by 0x100003C8D: main (main.c:309

回答1:

This is caused by the stdio library. A "Hello World" program is sufficient to reproduce it - just printf or fprintf to stdout or stderr. The first time you write to a FILE, it uses malloc to allocate an output buffer. This buffer allocation happens inside the __swsetup() function (download LibC source from Apple, you will see this in there; but actually, it is copied from FreeBSD, so many *BSD systems have the same function.) Now, when you call fclose() on the FILE, the buffer will be freed. The issue with standard streams (stdout, stderr), is one normally doesn't close them, as a result this buffer will normally never be freed.

You can make this "leak" go away by adding an fclose() on stdout and/or stderr before terminating your program. But honestly, there is no need to do that, you can just ignore it. This is a fixed sized buffer which is not going to grow in size, so it is not a "leak" as such. Closing stdout/stderr at the end of your program is not achieving anything useful.



回答2:

Valgrind is somewhat glitchy on Mac OS X; it doesn't have complete suppressions for some system libraries. (That is, it doesn't properly ignore some "expected" leaks.) Results will frequently include some spurious results like this, as well as some buffer overruns resulting from optimizations in functions like memcpy().

My advice? Avoid using valgrind on Mac OS X unless you are very familiar with the tool. Compile and test your application on a Linux system for best results.



标签: c macos valgrind