在尝试使用 __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++
不是一种选择。
我的问题有两个:
- 为什么两者的能见度不同?
- 我怎样才能访问这个符号?有没有办法动态获取它,或者仅静态链接到该符号所在的目标文件?
最佳答案
首先,可见性不同,因为在两者中,只有 __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/