簡體   English   中英

共享庫構造函數不起作用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM