linux 动态库构造函数,Linux共享库全局构造函数的相互依赖性
操作系統Centos 5.6 i686 2.6.18-53.1.4.el5vm.
gcc版本4.1.2 20080704(Red Hat 4.1.2-48)
ld版本2.17.50.0.6-6.el5 20061020
我以這種方式編譯:
gcc -c -fnon-call-exceptions -fexceptions -Wall -DUNICODE -D_UNICODE -D_REENTRANT -I.
并以這種方式鏈接:
gcc -lstdc -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L $SO_DIR $LIBRARIES
我有3個庫和一個可執行文件:A.so,B.so,C.so,ElfExec
B.so取決于A.so.
C.so取決于B.so.
在代碼A.so中具有通過其公開功能A.h的標頭,在代碼中B.so具有B.h標頭,其中包括A.h和B的功能.代碼中的C.so包括B.h.
A.h定義了一個靜態變量K,該類型可以在且僅當初始化A.so的靜態內存管理器時使用.變量K在頭文件A.h中直接定義,因此,它的初始化在組成B.so和C.so的所有對象的全局構造函數中傳播.
我像這樣鏈接所有內容:
gcc“所有B模塊” -lstdc -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L $SO_DIR A.so
gcc“所有C模塊” -lstdc -pthread -ldl -lrt-無重定位-Wl,-rpath,$SO_DIR -L $SO_DIR B.so
gcc“所有ElfExec模塊” -lstdc -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L $SO_DIR C.so
我也嘗試過:
gcc“所有ElfExec模塊” -lstdc -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L $SO_DIR A.so B.so C.so
ElfExec在運行時會收到SIGSEGV,因為它會在初始化A.so的靜態內存管理器之前嘗試初始化變量K.
這是因為C.so的全局構造函數在A.so的全局構造函數之前被調用.
如果我制作只需要B.so的應用程序ElfExec2
gcc“所有ElfExec1模塊” -lstdc -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L $SO_DIR B.so
這正常工作.
對于ElfExec1,鏈接器看到需要先調用A.so中的全局構造函數,然后再調用B.so中的全局構造函數.
在ElfExec的情況下,這不會受到限制.
我的解決方案是這樣鏈接C.so:
gcc“所有C模塊” -lstdc -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L $SO_DIR A.so B.so
這使C.so與A.so直接相關.
還有另一種方式可以告訴鏈接程序全局構造函數調用的順序嗎?
解決方法:
如您所見,不要相信鏈接器比您更了解.如果順序很重要,則需要以編程方式指定順序.不要只是試圖欺騙鏈接器.
如果這些不是庫,那就是您要做的,對吧?以正確的順序互相調用的構造函數/初始化函數?
我的第一選擇是將庫設計為不具有或使用全局變量.
如果您不能這樣做,那么我的第二個選擇是為每個需要初始化全局變量以具有init方法的庫.庫的使用者需要先調用該init方法,然后才能執行任何操作,并且庫必須嘗試阻止使用/構造,直到正確完成init為止.也許將它們靜態化為init方法,然后設置指向它們的全局指針(K * k)可能有助于實現.這應該足以使初始化鏈以正確的順序組合在一起.
最后,如果讓任何庫的用戶(對于A表示B,對于C表示B,對于C而言,C)的用戶都遇到障礙,則可以對gcc使用如下語言擴展:
extern "C" __attribute__ ((constructor)) void A_lib_ctor()
{
// ....
}
extern "C" __attribute__ ((destructor)) void A_lib_dtor()
{
// ....
}
在加載庫時自動執行所需的操作.這犧牲了一些可移植性.可能會犧牲更多,較新版本的gcc支持構造函數(優先級)語法.
我的最后選擇是使用dlopen手動加載庫的復雜步驟.
對于您而言,最重要的選擇是設計更好,而后來的選擇則更糟.
標簽:gcc,linker,ld,linux
來源: https://codeday.me/bug/20191102/1991358.html
總結
以上是生活随笔為你收集整理的linux 动态库构造函数,Linux共享库全局构造函数的相互依赖性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言 1 %3c%3c -253,结构
- 下一篇: linux服务器u盘启动项检测不到,将U