不同我有一個應用程序(應用程序)和動態庫/共享對象(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的副本。
你說「按設計」,但它不喜歡很好的設計。難道你不能重寫它以避免以這種複雜的方式暴露這個符號嗎? – trojanfoe
如果需要全局狀態,則應用和共享對象具有全局變量的單獨副本是最自然的設計。爲每個共享對象分配全局變量的副本是默認行爲 - 即使在沒有__attribute__((弱))的clang中也是如此。如果沒有人提出任何更好的建議,那我就是這樣解決的:我將刪除__attribute__((weak))並執行舊的「extern int g_global;」在.h;和「int g_global;」在「.cpp」中。 但我們題外話,實際的問題是:「如果這是一個鏗鏘的錯誤,如果沒有,那麼有沒有一個選項讓gcc的行爲」。 – user3922059
你說的‘全球性’,但是共享/動態庫映射到地址空間如果他們有獨立的變量副本,那麼這個「全局」又是如何呢?這種行爲對我來說是直截了當的。 – trojanfoe