我最近在调试产品中的崩溃,并确定原因是 glibc 和 tcmalloc 暴露的内存分配符号冲突。我编写了以下示例代码来暴露此问题:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <assert.h>
#include <stdlib.h>
int main()
{
struct addrinfo hints = {0}, *res = NULL;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int rc = getaddrinfo("myserver", NULL, &hints, &res);
assert(rc == 0);
return 0;
}
我使用以下命令编译它:
g++ temp.cpp -g -lresolv
我使用以下命令执行了程序:
LD_PRELOAD=/path/to/libtcmalloc_minimal.so.4 ./a.out
该程序因以下堆栈而崩溃:
#0 0x00007ffff6c7c875 in *__GI_raise (sig=) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x00007ffff6c7de51 在 *__GI_abort () at abort.c:92
#2 0x00007ffff6cbd8bf in __libc_message (do_abort=2, fmt=0x7ffff6d8c460 "*** glibc detected *** %s: %s: 0x%s ***\n") at ../sysdeps/unix/sysv/linux/ libc_fatal.c:186
#3 0x00007ffff6cc30c8 in malloc_printerr (action=2, str=0x7ffff6d88fec "free(): invalid pointer", ptr=) at malloc.c:6282
#4 0x00007ffff6cc810c in *__GI___libc_free (mem=) at malloc.c:3733
#5 0x00007ffff6839e89 in _nss_dns_gethostbyname4_r (name=0x400814 "myserver", pat=0x7fffffffdfa8, buffer=0x7fffffffd9b0 "myserver.mydomain.com", buflen=1024, errnop=0x7fffffffdfbc, herrnop=0x7fffffffdf98, ttlp=0x0) at nss_dns/dns-host .c:341
#6 0x00007ffff6d11917 in gaih_inet (name=0x400814 "myserver", service=0x7fffffffdf88, req=0x7ffffffffe1d0, pai=0x7ffffffffe160, naddrs=0x7ffffffffe168) at ../sysdeps/posix/getaddrinfo.c:880
#7 0x00007ffff6d14301 in *__GI_getaddrinfo (name=0x400814 "myserver", service=0x0, hints=0x7ffffffffe1d0, pai=0x7ffffffffe200) at ../sysdeps/posix/getaddrinfo.c:2452
#8 0x00000000004006f0 在 main () at temp.cpp:12
原因是 from 调用的函数free()
是from ,而对应的函数是from调用的。tcmalloc 的地址和函数正在进入导致这次崩溃的 GOT。如果我不将我的程序链接到._nss_dns_gethostbyname4_r()
libnss_dns.so
libc.so
malloc()
libresolv.so
libtcmalloc_minimal.so
malloc()
free()
libresolv.so
libresolv.so
现在我的问题。是否有任何文档解释如何安全地使用 tcmalloc 来避免这样的崩溃?