2015-11-17 54 views
4

不同我有一個應用程序(應用程序)和動態庫/共享對象(DLIB),兩者都針對其聲明一個全局變量靜態庫(GVAR)連接的在頭文件中使用__declspec (selectany)/__attribute__ ((weak))。通過設計,應用程序和dlib都應該有自己的gvar副本(在MSVC和GCC上我就是這樣)。處理__attribute__的((弱))是在鐺和gcc

移植到Mac OSX和鏗鏘編譯後我看到,在DLIB GVAR鏈接在應用GVAR。不知道這是否是一個叮咚的bug或通過設計;如果是通過設計,是否有任何方法可以避免它並獲得與GCC/MSVC中相同的行爲?

鐺版本:

bash-3.2$ c++ --version 
Apple LLVM version 7.0.0 (clang-700.1.76) 
Target: x86_64-apple-darwin15.0.0 
Thread model: posix 

最少的項目來重現問題:

main.cpp中:

#include <stdio.h> 
#include <dlfcn.h> 

__attribute__ ((weak)) int g_global = 10; 

int main() 
{ 
    printf ("main(): g_global: addr = %p; value = %d\n", &g_global, g_global); 

    typedef void Foo(); 

    void* so = dlopen ("./my-so.so", RTLD_LAZY | RTLD_LOCAL); 
    Foo* foo = (Foo*) dlsym (so, "foo"); 
    foo(); 
} 

shared.cpp:

#include <stdio.h> 

__attribute__ ((weak)) int g_global = 20; 

extern "C" void foo() 
{ 
    printf ("foo(): g_global: addr = %p; value = %d\n", &g_global, g_global); 
} 

build.sh :

#!/bin/bash 

rm -f my-so.so 
rm -f app. 

c++ -shared -fPIC shared.cpp -omy-so.so 
c++ main.cpp -oapp -ldl 

輸出:

bash-3.2$ ./app 
main(): g_global: addr = 0x10c657030; value = 10 
foo(): g_global: addr = 0x10c657030; value = 10 

需要注意的是,如果我刪除屬性((弱)),那麼應用程序和DLIB得到自己GVAR的副本。

+0

你說「按設計」,但它不喜歡很好的設計。難道你不能重寫它以避免以這種複雜的方式暴露這個符號嗎? – trojanfoe

+0

如果需要全局狀態,則應用和共享對象具有全局變量的單獨副本是最自然的設計。爲每個共享對象分配全局變量的副本是默認行爲 - 即使在沒有__attribute__((弱))的clang中也是如此。如果沒有人提出任何更好的建議,那我就是這樣解決的:我將刪除__attribute__((weak))並執行舊的「extern int g_global;」在.h;和「int g_global;」在「.cpp」中。 但我們題外話,實際的問題是:「如果這是一個鏗鏘的錯誤,如果沒有,那麼有沒有一個選項讓gcc的行爲」。 – user3922059

+0

你說的‘全球性’,但是共享/動態庫映射到地址空間如果他們有獨立的變量副本,那麼這個「全局」又是如何呢?這種行爲對我來說是直截了當的。 – trojanfoe

回答

2

我已經找到了答案在這裏: https://gcc.gnu.org/wiki/Visibility

爲了得到我想要的行爲,我不得不添加-fvisibility =隱藏的命令行,並添加屬性((能見度(「默認」)) )到需要導出的符號。