我最近正在调试产品中的崩溃,并确定原因是由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 in * __ GI_abort()at abort.c:92
#2 0x00007ffff6cbd8bf in __libc_message(do_abort = 2,fmt = 0x7ffff6d8c460&#34; *** glibc检测到***%s:%s:0x%s *** \ n&#34;)at ../ sysdeps / UNIX / SYSV / LINUX / libc_fatal.c:186
malloc_printerr中的#3 0x00007ffff6cc30c8(action = 2,str = 0x7ffff6d88fec&#34; free():无效指针&#34;,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&#34; myserver&#34;,pat = 0x7fffffffdfa8,buffer = 0x7fffffffd9b0&#34; myserver.mydomain.com&#34;,buflen = 1024,errnop = 0x7fffffffdfbc,herrnop = 0x7fffffffdf98,ttlp = 0x0)在nss_dns / dns-host.c:341
#6 0x00007ffff6d11917在gaih_inet(名称= 0x400814&#34; myserver&#34;,服务= 0x7fffffffdf88,req = 0x7fffffffe1d0,pai = 0x7fffffffe160,naddrs = 0x7fffffffe168)at ../sysdeps/posix/getaddrinfo.c:880
#7 0x00007ffff6d14301 in * __ GI_getaddrinfo(name = 0x400814&#34; myserver&#34;,service = 0x0,hints = 0x7fffffffe1d0,pai = 0x7fffffffe200)at ../sysdeps/posix/getaddrinfo.c:2452
#8 0x00000000004006f0 in main()at temp.cpp:12
原因是来自free()
的{{1}}调用的_nss_dns_gethostbyname4_r()
函数来自libnss_dns.so
而libc.so
来自malloc()
来自libresolv.so
。 tcmalloc的libtcmalloc_minimal.so
和malloc()
函数的地址正在进入导致此崩溃的free()
的GOT。如果我不将我的程序链接到libresolv.so
,那么崩溃就会消失。
现在提出我的问题。是否有任何文档解释如何安全地使用tcmalloc来避免这样的崩溃?
答案 0 :(得分:1)
glibc有一些插入Film
的文档:
我最好的猜测是你正在使用一些SUSE glibc变体which uses RTLD_DEEPBIND
for NSS modules。这导致known issue with malloc
interposition。 SUSE建议setting the RTLD_DEEPBIND=0
environment variable作为解决方法。