mangle
但是我们今天关注的不是RTTI,而是关注与通过type_info获取到的名称信息,type_info有一个name()的方法,返回const char*,但是这个name到底是什么在C++规范中没有限定,因此不同编译器返回的结果不同,例如下面的代码:
cout<<typeid(std::string)<<endl;
如果使用vc编译器进行编译,将返回:
class std::basic_string<char,struct std::char_traits,class std::allocator >
而g++编译执行时返回的却是:
Ss
后者很难理解,因为这是mangle后的符号名,而VC编译器返回的是demangle后的结果。使用C++的类与函数编译成obj文件后,都是使用mangle后的符号名。例如:假如我们编译了某个linux静态库,可以用nm工具查看其内部包含接口的符号(windows下可以使用dumpbin):
nm libmyfunc.a
其会返回许多mangle后的符号名,它们其实就是我们在库中编写的函数接口。
demangle
将C++ ABI标识符(C++ ABI identifier)转换成C++源程序标识符(original C++ source identifier)的过程称为demangle。更简单的说,识别C++编译以后的函数名的过程,就叫demangle。
在libstdc++里关于abi命名空间的文档中(https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/namespaces.html),介绍了GCC所使用的跨厂商(cross-vendor) C++ ABI,其中暴露的一个函数abi::__cxa_demangle就是用于demangling。
像C++ filt,连接器(linker)及其他的工具,都具有解析C++ ABI名称的能力,比如,使用C++filt命令行工具来demangle名字:
robin@centos7:~/blog$ c++filt St13bad_exception
std::bad_exception
现在你也可以做到(这个函数本身可能使用不同的demanglers,但是它所提供的抽象接口让你不用关心具体的实现)。
在如下情况你会关注demangle:
运行时阶段你想查看RTTI中的typeid字符串;
当你在处理runtime-support异常类时。
完整介绍