【问题标题】:handling of __attribute__ ((weak)) is different in clang and gcc对 __attribute__ ((weak)) 的处理在 clang 和 gcc 中是不同的
【发布时间】:2016-02-18 12:39:04
【问题描述】:

我有一个应用程序 (app) 和一个动态库/共享对象 (dlib),它们都链接到一个静态库,该静态库使用 __declspec (selectany) / __attribute__ ((weak)) 在头文件中声明一个全局变量 (gvar)。按照设计,app 和 dlib 都应该有自己的 gvar 副本(在 MSVC 和 GCC 上,我完全明白)。

移植到 Mac OSX 并使用 clang 编译后,我看到 dlib 中的 gvar 链接到 app 中的 gvar。不确定这是一个clang错误还是设计使然;如果是设计使然,有什么办法可以避免它并获得与 GCC/MSVC 中相同的行为?

clang 版本:

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

请注意,如果我删除 attribute ((weak)),那么 app 和 dlib 会获得它们自己的 gvar 副本。

【问题讨论】:

  • 您说“设计”,但它不喜欢非常好的设计。难道你不能重写它以避免以如此复杂的方式暴露这个符号吗?
  • 如果需要全局状态,那么为应用程序和共享对象分别创建全局变量副本是最自然的设计。为每个共享对象拥有单独的全局变量副本是默认行为——即使在没有 attribute((弱))的 clang 中也是如此。如果没有人提出更好的建议,这就是我将如何解决它:我将删除 attribute ((weak)) 并执行老式的“extern int g_global;”在.h;和“int g_global;”在“.cpp”中。但是我们跑题了,实际的问题是“如果这是一个 clang 错误,如果不是,那么是否可以选择获取 gcc 行为”。
  • 你说“全局”,但是共享/动态库被映射到进程的地址空间,所以如果它们有单独的变量副本,那么这个“全局”如何?这种行为对我来说是违反直觉的。

标签: c++ macos gcc clang


【解决方案1】:

我在这里找到了答案: https://gcc.gnu.org/wiki/Visibility

为了获得我想要的行为,我必须将-fvisibility=hidden 添加到命令行,并将__attribute__ ((visibility ("default"))) 添加到需要导出的符号中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-12
    • 2014-10-26
    相关资源
    最近更新 更多