利用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
[[email protected] hello]$ objdump a.out -x |grep NEEDED
NEEDED libc.so.6
[[email protected] 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
[[email protected] hello]$ gcc hello.c -ltcmalloc
[[email protected] hello]$ objdump a.out -x |grep NEEDED
NEEDED libtcmalloc.so.4
NEEDED libc.so.6
[[email protected] 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在前
[[email protected] hello]$ gcc hello.c -lc -ltcmalloc
[[email protected] hello]$ objdump a.out -x |grep NEEDED
NEEDED libc.so.6
NEEDED libtcmalloc.so.4
[[email protected] 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在前
[[email protected] hello]$ gcc hello.c -ltcmalloc -lc
[[email protected] hello]$ objdump a.out -x |grep NEEDED
NEEDED libtcmalloc.so.4
NEEDED libc.so.6
[[email protected] 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