2015-11-17 32 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 =隐藏的命令行,并添加属性((能见度(“默认”)) )到需要导出的符号。