在尝试使用__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++
静态链接不是一种选择。
我的问题有两个:
答案 0 :(得分:0)
首先,可见性是不同的,因为在这两者中,__cxa_demangle
标头中只声明了<cxxabi.h>
。该标头包含#pragma GCC visibility push(default)
,可确保在使用-fvisibility=hidden
进行编译时,其中的所有声明都可见。
其次,您可以静态链接到libstdc ++或者链接到libiberty。 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"};