2014-01-23 50 views
6

我有一個共享庫(libtest.cpp)和一個簡單的程序(test.cpp)。我想讓他們共享一個線程局部變量gVar。共享庫通過LD_PRELOAD鏈接。LD_PRELOAD和線程局部變量

這裏是我的共享庫libtest.cpp代碼:

#include<stdio.h> 

__thread int gVar; 

void print_gVar(){ 
    printf("%d\n", gVar); 
} 

下面是TEST.CPP的代碼。

#include<stdio.h> 

__thread int gVar; 

void __attribute__((weak)) print_gVar(); 

int main(){ 
    gVar = 10; 
    print_gVar(); 
    return 0; 
} 

我用下面的腳本來編譯和運行它們。

g++ -g -shared -fPIC -olibtest.so libtest.cpp 
g++ -g -fPIC -o test test.cpp 
LD_PRELOAD=./libtest.so ./test 

預期的結果是10,因爲test.cpp中的賦值會影響libtest.cpp中的gVar。但是,我只得到0.似乎libtest.cpp中的gVar和test.cpp中的gVar沒有鏈接。

我做了一些額外的測試:

如果我的任何文件添加到__attribute__((weak))gVar報關,輸出仍爲0

如果我從兩個文件中刪除__thread,那麼結果是10(成功)。

如果我將extern__attribute__((weak))添加到libtest.cpp中的gVar的聲明中,會出現分段錯誤。

我想LD_PRELOAD__thread肯定有問題。但我無法弄清楚。

任何人都可以告訴我如何使它工作?非常感謝你!

回答

5

這是不可能的,因爲線程本地存儲需要每個線程的初始化。

LD_PRELOAD即使在加載標準庫之前也會加載該庫,這會混淆TLS初始化。

更新:

請仔細閱讀第2和的ELF Handling For Thread-Local Storage

+0

3非常感謝您!你能否給我多些參考? – ZillGate

+0

不客氣,只是添加了它。可悲的是,沒有提到這個問題的具體問題,但你應該首先了解TLS初始化的工作原理。 – voodooattack

+0

@voodooattack我不太明白你的答案。你能詳細說明它爲什麼不起作用嗎?另外,你是否暗示LD_PRELOADed庫不能使用tls?這聽起來對我不正確。許多場景需要使用LD_PRELOADed庫以及tls,對吧?例如,https://github.com/jemalloc/jemalloc/issues/937 – Infinite