c++ - 静态 libstdc++.a 中的全局符号在共享 libstdc++.so 中是局部的

标签 c++ linker g++ libstdc++

在尝试使用 __gcclibcxx_demangle_callback 作为 __cxa_demangle 的非分配替代方案时,我遇到了一个给我带来一些麻烦的问题。当我静态链接 libstdc++ 时,找到了符号,但是当我动态链接时,g++ 报告:

undefined reference to `__gcclibcxx_demangle_callback'

奇怪的是,nm 将它列在其中一个而不是另一个:

me@compy:/lib$ nm libstdc++.a | grep demangle
0000543d T __cxa_demangle
0000550d T __gcclibcxx_demangle_callback
me@compy:/lib$ nm -D libstdc++.so | grep demangle
0004eabd T __cxa_demangle

readelf 的输出提示了原因 - 它在静态中是全局的,在共享中是局部的:

me@compy:/lib$ readelf -s libstdc++.a | grep demangle
   179: 0000543d   208 FUNC    GLOBAL DEFAULT    1 __cxa_demangle
   180: 0000550d    32 FUNC    GLOBAL DEFAULT    1 __gcclibcxx_demangle_callback
me@compy:/lib$ readelf -s libstdc++.so | grep demangle
  8313: 0004eb8d    32 FUNC    LOCAL  DEFAULT   12 __gcclibcxx_demangle_callback
 10871: 0004eabd   208 FUNC    GLOBAL DEFAULT   12 __cxa_demangle

将我的整个应用程序静态链接到 libstdc++ 不是一种选择。

我的问题有两个:

  1. 为什么两者的能见度不同?
  2. 我怎样才能访问这个符号?有没有办法动态获取它,或者仅静态链接到该符号所在的目标文件?

最佳答案

首先,可见性不同,因为在两者中,只有 __cxa_demangle<cxxabi.h> 中声明 header 。该 header 包含 #pragma GCC visibility push(default)这确保其中的所有声明在使用 -fvisibility=hidden 编译时可见.

其次,您可以静态链接到 libstdc++ 或者链接到 libiberty。自由导出 cplus_demangle_v3_callback它使用与 __gcclibcxx_demangle_callback 相同的底层函数.它只是没有任何参数检查,也没有选择所需的 demangling 选项。你可以这样调用它:

template <typename F>
struct lambda_caller
{
    F f;
    constexpr lambda_caller(F f) : f(std::move(f)) {}
    static void call(const char* data, size_t length, void* self)
    {
        static_cast<lambda_caller*>(self)->f(data, length);
    }
};

if (!lambda_caller callback{[&](const char* data, size_t length) {
        ::write(STDERR_FILENO, data, length);
    }}; ::cplus_demangle_v3_callback(mangled_name, DMGL_PARAMS | DMGL_TYPES,
                                   &callback::call, &callback))
    throw std::invalid_argument
        "mangled_name is not validly mangled according to C++ ABI rules"};

关于c++ - 静态 libstdc++.a 中的全局符号在共享 libstdc++.so 中是局部的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31629102/

相关文章:

c++ - msvc/permissive- std::string 重载运算符 '=' 不明确

C++ - 二进制表达式的无效操作数

GCC 链接到共享对象的链接器名称

c++ - .cpp 和 .h 文件的不同处理方式?

linker - 使用 mingw 链接到 libav* 的 undefined reference

c++ - 为什么 boost::timer 的结果如此奇怪?

linux - 如何在共享库中的链接时(不是加载时)解析弱符号

c++ - 删除间接指针是否正确

C++ boost json ptree 解析器无法解析字符串

c++ - 是什么导致我的堆栈中出现神秘的重复条目?