Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在clang和gcc中,_属性__((弱))的处理是不同的_C++_Macos_Gcc_Clang - Fatal编程技术网

C++ 在clang和gcc中,_属性__((弱))的处理是不同的

C++ 在clang和gcc中,_属性__((弱))的处理是不同的,c++,macos,gcc,clang,C++,Macos,Gcc,Clang,我有一个应用程序(app)和一个动态库/共享对象(dlib),它们都与一个静态库相链接,该静态库使用\uuu declspec(selectany)/\uuu属性(弱))在头文件中声明一个全局变量(gvar)。通过设计,应用程序和dlib都应该有自己的gvar副本(在MSVC和GCC上,我完全可以得到) 在移植到MacOSX并使用clang编译之后,我看到dlib中的gvar链接到了应用程序中的gvar。不确定这是一个叮当作响的bug还是出于设计;如果它是设计的,有没有办法避免它并获得与GCC/

我有一个应用程序(app)和一个动态库/共享对象(dlib),它们都与一个静态库相链接,该静态库使用
\uuu declspec(selectany)
/
\uuu属性(弱))
在头文件中声明一个全局变量(gvar)。通过设计,应用程序和dlib都应该有自己的gvar副本(在MSVC和GCC上,我完全可以得到)

在移植到MacOSX并使用clang编译之后,我看到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 ();
}
输出:

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

请注意,如果我删除属性((弱)),则app和dlib将获得它们自己的gvar副本。

我在这里找到了答案:


为了获得我想要的行为,我必须将
-fvisibility=hidden
添加到命令行中,并将
\uuuu属性(可见性(“默认”))
添加到需要导出的符号中。

你说“按设计”,但它不喜欢非常好的设计。您不能重写它以避免以如此复杂的方式暴露此符号吗?如果需要全局状态,那么为应用程序和共享对象提供单独的全局变量副本是最自然的设计。为每个共享对象的全局变量提供单独的副本是默认行为——即使在没有属性((弱))的情况下也是如此。如果没有人提出更好的建议,我将这样做:删除属性((弱))并在.h中执行老派的“extern int g_global;”;和“int g_global”,“in”.cpp”。但我们已经离题了,实际的问题是“如果这是一个叮当作响的bug,如果不是,那么是否有一个获得gcc行为的选项”。你说“全局”,但是共享/动态库被映射到进程的地址空间,所以如果它们有变量的单独副本,这是如何“全局”的?这种行为对我来说是违反直觉的。
#!/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