![](/img/trans.png)
[英]Why is __attribute__((constructor)) in my shared library not working?
[英]shared library constructor not working
在共享庫中,我必須在加載時進行某些初始化。 如果我使用GCC屬性__attribute__ ((constructor))
定義函數,則該函數將不起作用,即,在加載鏈接我的共享庫的程序時,不會調用該函數。
如果我將函數名稱更改為_init()
,它將起作用。 顯然,現在不建議使用_init()
和_fini()
函數。
知道為什么__attribute__ ((constructor))
不起作用嗎? 這是Linux 2.6.9, gcc
版本3.4.6
編輯:
例如,假設庫代碼如下:
#include <stdio.h>
int smlib_count;
void __attribute__ ((constructor)) setup(void) {
smlib_count = 100;
printf("smlib_count starting at %d\n", smlib_count);
}
void smlib_count_incr() {
smlib_count++;
smlib_count++;
}
int smlib_count_get() {
return smlib_count;
}
要構建.so,請執行以下操作:
gcc -fPIC -c smlib.c
ld -shared -soname libsmlib.so.1 -o libsmlib.so.1.0 -lc smlib.o
ldconfig -v -n .
ln -sf libsmlib.so.1 libsmlib.so
由於.so不在標准位置之一,因此我更新了LD_LIBRARY_PATH
並從另一個程序鏈接了.so。 構造函數不會被調用。 如果我將其更改為_init()
,它將起作用。
好的,所以我看了一下,看起來好像是中間的gcc
步驟(使用-c
)引起了問題。 這是我對所見內容的解釋。
當您使用setup()
編譯為.o
時, gcc
會將其視為普通函數(因為您沒有將其編譯為.so
,所以它不在乎)。 然后, ld
在ELF的動態部分中看不到任何_init()
或類似DT_INIT
任何東西,並假定沒有構造函數。
當使用_init()
編譯為.o
時, gcc
還將其視為普通函數。 實際上,在我看來, 目標文件是相同的,除了函數本身的名稱! 因此, ld
再次查看.o
文件,但是這次看到的是_init()
函數,該函數知道正在查找的函數,並確定它是構造函數,並相應DT_INIT
在新的.so
創建了DT_INIT
條目。
最后,如果一步完成編譯和鏈接,如下所示:
gcc -Wall -shared -fPIC -o libsmlib.so smlib.c
然后,發生的事情是gcc
在創建共享庫的上下文中看到並理解了__attribute__ ((constructor))
,並DT_INIT
創建了DT_INIT
條目。
簡短版本:使用gcc
一步即可進行編譯和鏈接。 您可以使用-Wl
(請參見手冊頁)來傳遞額外的選項,例如-soname
如果需要),例如-Wl,-soname,libsmlib.so.1
。
從此鏈接 :
“共享庫不得使用gcc參數-nostartfiles”或-nostdlib進行編譯。如果使用這些參數,則將不執行構造函數/析構函數例程(除非采取特殊措施)。
使用-nostdlib時,gcc / ld不會將elf頭中的DT_INIT位置1。 在兩種情況下,您都可以檢查objdump -p並查找INIT部分。 在屬性 ((constructor))的情況下,您將找不到該INIT節。 但是對於__init情況,您將在共享庫中找到INIT部分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.