【发布时间】:2014-08-03 10:41:59
【问题描述】:
一段时间以来,我一直在使用一些解构代码来帮助进行一些调试,而无需编写数千行动态强制转换或实现返回类名的虚函数。
template <class CLASS>
std::string getClassName(CLASS &theObject)
{
int status = 0;
// Convert real name to readable string
char *realName = abi::__cxa_demangle(typeid(theObject).name(), nullptr,
nullptr, &status);
ASSERT(status == 0); // Assert for success
VERIFY(realName, return std::string());
// Return as string + prevent memory leaks!
const std::string result(realName);
free(realName);
return result;
}
这段代码背后的想法很简单,输出我们实际使用的类。 虽然在切换到 Ubuntu 14.04 后,我不再能够使用 clang 和 c++-11/c++-14 标准进行编译,所以我已经切换到使用 libc++ 而不是 libstdc++。
切换到 libc++ 后,我注意到当我对 'std::string' 进行 demangle 时,它不再输出 'std::string',而是输出:
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >
当然这是正确的,因为 std::string 是 std::basic_string 的 typedef。 尽管据我所见,在 libc++ 和 libstdc++ 中,这都是使用 typedef 以相同的方式定义的。所以我真的不明白为什么切换到 libc++ 会改变这种解构。
有人知道为什么这是不同的,以及如果 CLASS 是“std::string”,如何获得“std::string”,如果 CLASS 是“myTemplate”,如何获得“myTemplate”?
Tnx 提前!
JVApen
【问题讨论】:
-
阅读 C++ itanium ABI 文档。
std::basic_string有一个特殊的名称修饰,但std::__1::basic_string没有。您将不得不使用一些后处理。 -
据我所知,Clang 标准库实现将东西放在
__1命名空间(我想支持版本控制,然后命名空间通过内联命名空间加入std)。由于他们使用的是 GCC 的 demangler,因此该 demangler 不会处理 LLVM/Clang 命名约定。 -
我有 /usr/include/c++/v1/cxxabi.h,如果我理解正确的话,它是 libc++ 版本,而不是 libstdc++ 版本。因此,要么它以某种方式与错误的库链接,要么 libc++-abi 无法破解自己的结构
标签: c++ string c++11 libc++ demangler