tcmalloc库使用测试

利用LD_PRELOAD来加载tcmalloc库
在编译时显式链接tcmalloc库
试验
试验1:不链接tcmalloc
试验2:仅显式链接tcmalloc
试验3:显式链接libc和tcmalloc,libc在前
试验4:显式链接libc和tcmalloc,tcmalloc在前
结论

利用LD_PRELOAD来加载tcmalloc库
那么用户调用malloc肯定是走到tcmalloc中;

在编译时显式链接tcmalloc库
如何保证在运行时,malloc符号是绑定到tcmalloc内的?
仅通过动态库加载顺序?还是有其它机制?

试验
x86_64平台。
写一个hello小程序,调用一次malloc函数。
利用如下命令来查看依赖库及malloc符号的绑定结果:
objdump -x a.out |grep NEEDED
LD_DEBUG=bindings ./a.out

试验1:不链接tcmalloc
[lubo@localhost hello]$ objdump a.out -x |grep NEEDED
NEEDED libc.so.6

[lubo@localhost hello]$ LD_DEBUG=bindings ./a.out
5363: initialize program: ./a.out
5363:
5363:
5363: transferring control: ./a.out
5363:
5363: binding file ./a.out [0] to /lib64/libc.so.6 [0]: normal symbol `malloc' [GLIBC_2.2.5]
5363: binding file ./a.out [0] to /lib64/libc.so.6 [0]: normal symbol `memset' [GLIBC_2.2.5]
5363:
5363: calling fini: ./a.out [0]


试验2:仅显式链接tcmalloc
[lubo@localhost hello]$ gcc hello.c -ltcmalloc
[lubo@localhost hello]$ objdump a.out -x |grep NEEDED
NEEDED libtcmalloc.so.4
NEEDED libc.so.6

[lubo@localhost hello]$ LD_DEBUG=bindings ./a.out
5414: initialize program: ./a.out
5414:
5414:
5414: transferring control: ./a.out
5414:
5414: binding file ./a.out [0] to /lib64/libtcmalloc.so.4 [0]: normal symbol `malloc'
5414: binding file ./a.out [0] to /lib64/libc.so.6 [0]: normal symbol `memset' [GLIBC_2.2.5]
5414:
5414: calling fini: ./a.out [0]


试验3:显式链接libc和tcmalloc,libc在前
[lubo@localhost hello]$ gcc hello.c -lc -ltcmalloc
[lubo@localhost hello]$ objdump a.out -x |grep NEEDED
NEEDED libc.so.6
NEEDED libtcmalloc.so.4

[lubo@localhost hello]$ LD_DEBUG=bindings ./a.out
5463: initialize program: ./a.out
5463:
5463:
5463: transferring control: ./a.out
5463:
5463: binding file ./a.out [0] to /lib64/libc.so.6 [0]: normal symbol `malloc' [GLIBC_2.2.5]
5463: binding file ./a.out [0] to /lib64/libc.so.6 [0]: normal symbol `memset' [GLIBC_2.2.5]
5463:
5463: calling fini: ./a.out [0]

试验4:显式链接libc和tcmalloc,tcmalloc在前
[lubo@localhost hello]$ gcc hello.c -ltcmalloc -lc
[lubo@localhost hello]$ objdump a.out -x |grep NEEDED
NEEDED libtcmalloc.so.4
NEEDED libc.so.6

[lubo@localhost hello]$ LD_DEBUG=bindings ./a.out
5501: initialize program: ./a.out
5501:
5501:
5501: transferring control: ./a.out
5501:
5501: binding file ./a.out [0] to /lib64/libtcmalloc.so.4 [0]: normal symbol `malloc'
5501: binding file ./a.out [0] to /lib64/libc.so.6 [0]: normal symbol `memset' [GLIBC_2.2.5]
5501:
5501: calling fini: ./a.out [0]

结论
经过上述测试验证(也作了libstdc++ / new函数的测试),
当显式链接libtcmalloc时,进程的malloc/new最终能不能调到tcmalloc中,取决于进程对动态库的依赖顺序。
如果编译软件时,既显式链接libc(或libstdc++),又显式链接libtcmalloc,那么必须保证先链接tcmalloc再链接libc(或libstdc++),否则,malloc/new函数还是被绑定到原生的libc(或libstdc++)中。

延伸:
进程加载多个依赖库时,可以选择广度优先遍历加载,也可以选择深度优先遍历加载,不同的加载策略,会导致某些动态库的加载顺序发生变化,如果多个动态库中含有相同的动态符号,那么会产生不同的符号绑定结果。但对于tcmalloc来说,只要不显示链接libc(或libstdc++),一般就没什么问题,因为不管广度优先还是深度优先,tcmalloc必然在libc(libstdc++)之前先被加载。
————————————————
版权声明:本文为CSDN博主「bobbypollo」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/bobbypollo/article/details/79906985

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章