c - 由于 getaddrinfo() 导致 Valgrind 内存泄漏

标签 c sockets tcp memory-leaks valgrind

我将 TCP 流套接字连接到给定的主机名和端口。为了获取主机的 IP 地址,我使用 getaddrinfo()如下

struct addrinfo hints;
struct addrinfo *result, *server;

memset(&hints, 0, sizeof(struct addrinfo)); // fill server with 0

hints.ai_family = AF_INET;   // set address family
hints.ai_protocol=0;    // set protocol type to auto
hints.ai_socktype = SOCK_STREAM;    // set type of socket to stream socket

if(getaddrinfo(HOSTNAME,PORT,&hints,&result)){
    perror("Could not resolve IP from given hostname and port (getaddrinfo)");
    freeaddrinfo(result);
    return -1;
}

if(print) printf("Connecting socket ... \n");
int connectFlag=1;
for(server=result;server!=NULL;server=server->ai_next){
    if(connect(sockfd,server->ai_addr,server->ai_addrlen)==-1){
        continue;
    }
    if(print){
        printf("Socket successfully connected\n");
    }
    break;
}
    
if(!connectFlag){
    printf("Could not connect to server %s.\n",HOSTNAME);
    close(sockfd);
    freeaddrinfo(result);
    return -1;
}

freeaddrinfo(result);

所有这些都发生在接收参数的函数内

int sockfd = socket(AF_INET,SOCK_STREAM,0);

来自另一个函数。一切正常,套接字已连接,我按预期接收和发送消息。

问题是,当我检查我创建的二进制文件时

valgrind --leak-check=full --trace-children=yes ./binary

我得到 3313 字节仍然可达。当手动解析主机并直接使用 IP 连接时,我没有遇到泄漏。我用旧的 gethostbyname() 替换了 getaddrinfo()并获得完全相同数量的仍然可达的字节。

如何消除这些泄漏?

Valgrind 输出

   % valgrind --leak-check=full --show-leak-kinds=all ./play
==16353== Memcheck, a memory error detector
==16353== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==16353== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==16353== Command: ./a.out
==16353== 
==16353== 
==16353== HEAP SUMMARY:
==16353==     in use at exit: 3,313 bytes in 10 blocks
==16353==   total heap usage: 96 allocs, 86 frees, 54,234 bytes allocated
==16353== 
==16353== 64 bytes in 2 blocks are still reachable in loss record 1 of 5
==16353==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16353==    by 0x4016790: _dl_close_worker.part.0 (dl-close.c:393)
==16353==    by 0x4017029: _dl_close_worker (dl-close.c:125)
==16353==    by 0x4017029: _dl_close (dl-close.c:822)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353==    by 0x4F7CBAE: dlerror_run (dl-libc.c:46)
==16353==    by 0x4F7CBAE: __libc_dlclose (dl-libc.c:222)
==16353==    by 0x4FADB66: free_mem (in /lib/x86_64-linux-gnu/libc-2.23.so)
==16353==    by 0x4FAD78F: __libc_freeres (in /lib/x86_64-linux-gnu/libc-2.23.so)
==16353==    by 0x4A2868C: _vgnU_freeres (in /usr/lib/valgrind/vgpreload_core-amd64-linux.so)
==16353==    by 0x4E73FAA: __run_exit_handlers (exit.c:97)
==16353==    by 0x4E74044: exit (exit.c:104)
==16353==    by 0x404162: cleanUp (in /home/a)
==16353==    by 0x401CB7: dispatch (in /home/a)
==16353== 
==16353== 71 bytes in 2 blocks are still reachable in loss record 2 of 5
==16353==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16353==    by 0x401CD89: strdup (strdup.c:42)
==16353==    by 0x401860E: _dl_load_cache_lookup (dl-cache.c:311)
==16353==    by 0x4008F98: _dl_map_object (dl-load.c:2342)
==16353==    by 0x400D9D1: openaux (dl-deps.c:63)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353==    by 0x400E011: _dl_map_object_deps (dl-deps.c:254)
==16353==    by 0x4015411: dl_open_worker (dl-open.c:280)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353==    by 0x4014BD8: _dl_open (dl-open.c:660)
==16353==    by 0x4F7C9BC: do_dlopen (dl-libc.c:87)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353== 
==16353== 71 bytes in 2 blocks are still reachable in loss record 3 of 5
==16353==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16353==    by 0x400BD23: _dl_new_object (dl-object.c:165)
==16353==    by 0x400633C: _dl_map_object_from_fd (dl-load.c:1006)
==16353==    by 0x4008A56: _dl_map_object (dl-load.c:2476)
==16353==    by 0x400D9D1: openaux (dl-deps.c:63)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353==    by 0x400E011: _dl_map_object_deps (dl-deps.c:254)
==16353==    by 0x4015411: dl_open_worker (dl-open.c:280)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353==    by 0x4014BD8: _dl_open (dl-open.c:660)
==16353==    by 0x4F7C9BC: do_dlopen (dl-libc.c:87)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353== 
==16353== 744 bytes in 2 blocks are still reachable in loss record 4 of 5
==16353==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16353==    by 0x4011EED: _dl_check_map_versions (dl-version.c:293)
==16353==    by 0x4015948: dl_open_worker (dl-open.c:286)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353==    by 0x4014BD8: _dl_open (dl-open.c:660)
==16353==    by 0x4F7C9BC: do_dlopen (dl-libc.c:87)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353==    by 0x4F7CA73: dlerror_run (dl-libc.c:46)
==16353==    by 0x4F7CA73: __libc_dlopen_mode (dl-libc.c:163)
==16353==    by 0x4F623BD: nss_load_library (nsswitch.c:358)
==16353==    by 0x4F630F3: __nss_lookup_function (nsswitch.c:466)
==16353==    by 0x4F630F3: __nss_next2 (nsswitch.c:242)
==16353==    by 0x4F535FA: gethostbyname2_r@@GLIBC_2.2.5 (getXXbyYY_r.c:281)
==16353==    by 0x4F259DE: gaih_inet (getaddrinfo.c:622)
==16353== 
==16353== 2,363 bytes in 2 blocks are still reachable in loss record 5 of 5
==16353==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16353==    by 0x400BA25: _dl_new_object (dl-object.c:75)
==16353==    by 0x400633C: _dl_map_object_from_fd (dl-load.c:1006)
==16353==    by 0x4008A56: _dl_map_object (dl-load.c:2476)
==16353==    by 0x400D9D1: openaux (dl-deps.c:63)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353==    by 0x400E011: _dl_map_object_deps (dl-deps.c:254)
==16353==    by 0x4015411: dl_open_worker (dl-open.c:280)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353==    by 0x4014BD8: _dl_open (dl-open.c:660)
==16353==    by 0x4F7C9BC: do_dlopen (dl-libc.c:87)
==16353==    by 0x4010393: _dl_catch_error (dl-error.c:187)
==16353== 
==16353== LEAK SUMMARY:
==16353==    definitely lost: 0 bytes in 0 blocks
==16353==    indirectly lost: 0 bytes in 0 blocks
==16353==      possibly lost: 0 bytes in 0 blocks
==16353==    still reachable: 3,313 bytes in 10 blocks
==16353==         suppressed: 0 bytes in 0 blocks
==16353== 
==16353== For counts of detected and suppressed errors, rerun with: -v
==16353== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

如果我添加 valgrind 选项 --trace-children=yes valgrind 会检查子进程。我没有输出这个,因为泄漏发生在这个父进程中。

编辑

事实证明,我们无法在其他硬件上重现 valgrind 输出。在这台服务器上,getaddrinfo() 生成了 valgrind 输出以及 gethostbyname()。我们没有进一步观察这种行为可能来自何处。

最佳答案

“仍然可达”意味着程序已经分配了内存并且在终止时仍然有对其的引用。这可能意味着第一次调用时 getaddrinfo() 和 gethostbyname() 分配了可重用的内存。

这个SO-answer也可能适用:https://stackoverflow.com/a/13230399/2696475

关于c - 由于 getaddrinfo() 导致 Valgrind 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41829655/

相关文章:

无法修改乐鑫提供的 ESP8266 示例

c# - 如何在 ServiceStack 中禁用 Nagle 算法?

ios - iOS 中的多路径 TCP

php - 是否可以重新使用故意打开的套接字?

c# - 如果没有发送数据,TCP 套接字会在一段时间后自动关闭吗?

c - 使用 C Readline 从文件而不是标准输入中读取一行

c - fork() 在内部调用 clone() 是真的吗?

c - 找到文件,但名称未更新

python-3.x - 在非阻塞套接字上接收数据时如何解决阻塞错误

UNIX 域套接字与共享内存(映射文件)