不同我有一个应用程序(应用程序)和动态库/共享对象(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