1

Valgrind report me memory leak when i use getaddrinfo() and it fails with EAI_NODATA. When getaddrinfo() success, no memory leak reported.

My code:

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>

int main(void)
{
    struct addrinfo hints = {}, *addrs = NULL;
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

    int res;
 
    if ((res = getaddrinfo("exampleeeeeeeee.com", "443", &hints, &addrs)) != 0) {
        fprintf(stderr, "Failed to get address info: %s\n", gai_strerror(res));
        freeaddrinfo(addrs);
        return -1;
    }

    freeaddrinfo(addrs);
    return EXIT_SUCCESS;
}

With a valid hostname:

All heap blocks were freed -- no leaks are possible

With an "invalid" hostname (like exampleeeeeeeee.com):

Failed to get address info: No address associated with hostname
==18364== 
==18364== HEAP SUMMARY:
==18364==     in use at exit: 3,557 bytes in 8 blocks
==18364==   total heap usage: 92 allocs, 84 frees, 30,877 bytes allocated
==18364== 
==18364== 38 bytes in 1 blocks are still reachable in loss record 1 of 7
==18364==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==18364==    by 0x401C01A: strdup (strdup.c:42)
==18364==    by 0x40172CB: _dl_load_cache_lookup (dl-cache.c:320)
==18364==    by 0x4009776: _dl_map_object (dl-load.c:2102)
==18364==    by 0x400DD90: openaux (dl-deps.c:64)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x400E108: _dl_map_object_deps (dl-deps.c:248)
==18364==    by 0x4013D7A: dl_open_worker (dl-open.c:571)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x40138C9: _dl_open (dl-open.c:837)
==18364==    by 0x499963C: do_dlopen (dl-libc.c:96)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364== 
==18364== 38 bytes in 1 blocks are still reachable in loss record 2 of 7
==18364==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==18364==    by 0x400BFB7: _dl_new_object (dl-object.c:196)
==18364==    by 0x4007255: _dl_map_object_from_fd (dl-load.c:997)
==18364==    by 0x4009274: _dl_map_object (dl-load.c:2236)
==18364==    by 0x400DD90: openaux (dl-deps.c:64)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x400E108: _dl_map_object_deps (dl-deps.c:248)
==18364==    by 0x4013D7A: dl_open_worker (dl-open.c:571)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x40138C9: _dl_open (dl-open.c:837)
==18364==    by 0x499963C: do_dlopen (dl-libc.c:96)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364== 
==18364== 45 bytes in 1 blocks are still reachable in loss record 3 of 7
==18364==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==18364==    by 0x401C01A: strdup (strdup.c:42)
==18364==    by 0x40172CB: _dl_load_cache_lookup (dl-cache.c:320)
==18364==    by 0x4009776: _dl_map_object (dl-load.c:2102)
==18364==    by 0x4013D11: dl_open_worker (dl-open.c:513)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x40138C9: _dl_open (dl-open.c:837)
==18364==    by 0x499963C: do_dlopen (dl-libc.c:96)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x499A27E: _dl_catch_error (dl-error-skeleton.c:227)
==18364==    by 0x4999716: dlerror_run (dl-libc.c:46)
==18364==    by 0x49997A5: __libc_dlopen_mode (dl-libc.c:195)
==18364== 
==18364== 45 bytes in 1 blocks are still reachable in loss record 4 of 7
==18364==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==18364==    by 0x400BFB7: _dl_new_object (dl-object.c:196)
==18364==    by 0x4007255: _dl_map_object_from_fd (dl-load.c:997)
==18364==    by 0x4009274: _dl_map_object (dl-load.c:2236)
==18364==    by 0x4013D11: dl_open_worker (dl-open.c:513)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x40138C9: _dl_open (dl-open.c:837)
==18364==    by 0x499963C: do_dlopen (dl-libc.c:96)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x499A27E: _dl_catch_error (dl-error-skeleton.c:227)
==18364==    by 0x4999716: dlerror_run (dl-libc.c:46)
==18364==    by 0x49997A5: __libc_dlopen_mode (dl-libc.c:195)
==18364== 
==18364== 984 bytes in 2 blocks are still reachable in loss record 5 of 7
==18364==    at 0x483AB65: calloc (vg_replace_malloc.c:760)
==18364==    by 0x4011686: _dl_check_map_versions (dl-version.c:274)
==18364==    by 0x4013DC5: dl_open_worker (dl-open.c:577)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x40138C9: _dl_open (dl-open.c:837)
==18364==    by 0x499963C: do_dlopen (dl-libc.c:96)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x499A27E: _dl_catch_error (dl-error-skeleton.c:227)
==18364==    by 0x4999716: dlerror_run (dl-libc.c:46)
==18364==    by 0x49997A5: __libc_dlopen_mode (dl-libc.c:195)
==18364==    by 0x4981305: nss_load_library (nsswitch.c:359)
==18364==    by 0x4981B98: __nss_lookup_function (nsswitch.c:467)
==18364== 
==18364== 1,200 bytes in 1 blocks are still reachable in loss record 6 of 7
==18364==    at 0x483AB65: calloc (vg_replace_malloc.c:760)
==18364==    by 0x400BCDF: _dl_new_object (dl-object.c:89)
==18364==    by 0x4007255: _dl_map_object_from_fd (dl-load.c:997)
==18364==    by 0x4009274: _dl_map_object (dl-load.c:2236)
==18364==    by 0x400DD90: openaux (dl-deps.c:64)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x400E108: _dl_map_object_deps (dl-deps.c:248)
==18364==    by 0x4013D7A: dl_open_worker (dl-open.c:571)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x40138C9: _dl_open (dl-open.c:837)
==18364==    by 0x499963C: do_dlopen (dl-libc.c:96)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364== 
==18364== 1,207 bytes in 1 blocks are still reachable in loss record 7 of 7
==18364==    at 0x483AB65: calloc (vg_replace_malloc.c:760)
==18364==    by 0x400BCDF: _dl_new_object (dl-object.c:89)
==18364==    by 0x4007255: _dl_map_object_from_fd (dl-load.c:997)
==18364==    by 0x4009274: _dl_map_object (dl-load.c:2236)
==18364==    by 0x4013D11: dl_open_worker (dl-open.c:513)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x40138C9: _dl_open (dl-open.c:837)
==18364==    by 0x499963C: do_dlopen (dl-libc.c:96)
==18364==    by 0x499A1BF: _dl_catch_exception (dl-error-skeleton.c:208)
==18364==    by 0x499A27E: _dl_catch_error (dl-error-skeleton.c:227)
==18364==    by 0x4999716: dlerror_run (dl-libc.c:46)
==18364==    by 0x49997A5: __libc_dlopen_mode (dl-libc.c:195)
==18364== 
==18364== LEAK SUMMARY:
==18364==    definitely lost: 0 bytes in 0 blocks
==18364==    indirectly lost: 0 bytes in 0 blocks
==18364==      possibly lost: 0 bytes in 0 blocks
==18364==    still reachable: 3,557 bytes in 8 blocks
==18364==         suppressed: 0 bytes in 0 blocks

This memory leak exist in WikiBook's example with "invalid" hostname.

I tried to freeaddrinfo() everywhere.

Info:

OS: Debian Bullseye (testing) Linux linux 5.9.0-1-amd64 #1 SMP Debian 5.9.1-1 (2020-10-17) x86_64 GNU/Linux

libc: 2.31-4

gcc: 10.2.0-15

g0rbe
  • 33
  • 5
  • You shouldn't need to call `freeaddrinfo()` when it fails, but I don't think there's any harm. – Barmar Nov 04 '20 at 19:23
  • 1
    It sounds like the leak is internal to `getaddrinfo()` so there's nothing you can do about it. – Barmar Nov 04 '20 at 19:24
  • @Barmar Yes, i know. `addrs` is still `NULL` when fail. I just tested and hoped for some magic. – g0rbe Nov 04 '20 at 19:30
  • 1
    As mentioned in the other question, `getaddrinfo` probably allocates some memory permanently the first time it's called, for future reuse. – Barmar Nov 04 '20 at 19:32
  • Debian considered it as a bug, and "fixed" years ago: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818178 – g0rbe Nov 04 '20 at 20:10
  • @Barmar: There is harm. You can't pass to `freeaddrinfo` anything but a pointer resulting from a successful call to `getaddrinfo`. Doing so results in undefined behavior. – R.. GitHub STOP HELPING ICE Nov 04 '20 at 20:35
  • @R..GitHubSTOPHELPINGICE I assumed that it was like `free()`, allowing NULL to be passed and doing nothing. But I see now that the specification doesn't say so. – Barmar Nov 04 '20 at 20:38
  • @Barmar: The problem is deeper than that. `getaddrinfo` has no obligation (and arguably not even any allowance) to set `*res` to null on failure. If it's really forbidden from touching it on failure, initializing it to null yourself before the call would suffice, but otherwise accessing it after failure is undefined. As for whether you can pass a null pointer to `freeaddrinfo`, it's not clear and hingest on whether a null pointer is a "sublist" of a list returned by `getaddrinfo`. – R.. GitHub STOP HELPING ICE Nov 04 '20 at 21:44
  • @R..GitHubSTOPHELPINGICE So I guess `if (addrs) freeaddrinfo(addrs);` would be best. – Barmar Nov 04 '20 at 21:46

0 Answers0