Rtti and type_info
When C ++ enables the rtti (run-time type identification) feature during compilation, you can use the typeid operator in the Code (including <typeinfo> Of course). This symbol can be used for a variable or a class name to return a reference to a type_info object. During compilation, a unique type_info object will be created for each c ++ class that uses the rtti feature and contains the inheritance relationship, dynamic_cast is based on this object to determine whether the pointer of a base class object can be converted down to the pointer of a subclass object. The following is an example of using typeid:
#include <iostream> #include <string>#include <typeinfo>using namespace std;int main(){ string s; if(typeid(s) == typeid(string)) { cout<<"same type"<<endl; } else { cout<<"different type"<<endl; } return 0;}Mangle
However, we are not concerned with rtti today, but with the name information obtained through type_info. type_info has a name () method, and returns const char *, however, this name is not defined in the C ++ specification. Therefore, different compilers return different results, such as the following code:
Cout <typeid (STD: string) <Endl;
If you use the VC compiler for compilation, the following will be returned:
Class STD: basic_string <char, struct STD: char_traits <char>, class STD: Allocator <char>
While G ++ returns the following during compilation and execution:
SS
The latter is hard to understand, because this is the symbolic name after mangle, And the VC compiler returns the result after demangle. After the C ++ class and function are compiled into the OBJ file, the mangle symbol name is used. For example, if we have compiled a Linux static library, we can use the NM tool to view its internal symbols containing interfaces (dumpbin can be used in Windows ):
NM libmyfunc.
It will return many symbolic names after mangle, which are actually the function interfaces we have written in the library.
How can I convert such symbolic names into readable names? In fact, different compilers provide "resolution" functions, which can be encoded as follows:
#include <typeinfo>#include <string>#ifdef _MSC_VER#ifndef WIN32_LEAN_AND_MEAN#define WIN32_LEAN_AND_MEAN#endif#ifndef _WIN32_WINNT#define _WIN32_WINNT 0x0501#endif#include <windows.h>#include <Dbghelp.h>std::string CxxDemangle(const char* name){ char buffer[1024];DWORD length = UnDecorateSymbolName(name, buffer, sizeof(buffer), 0); if (length > 0) return std::string(buffer, length); else return name;}#pragma comment(lib, "DbgHelp")#elif defined __GNUC__#include <cxxabi.h>std::string CxxDemangle(const char* name){ char buffer[1024] = {0}; size_t size = sizeof(buffer); int status;char *ret; if (ret = abi::__cxa_demangle(name, buffer, &size, &status)) return std::string(ret); else return name;}#endif#include <iostream>#include <string>#include <typeinfo>using namespace std;int main(){string s;if(typeid(s) == typeid(string))cout<<typeid(std::string).name()<<endl;cout<<CxxDemangle(typeid(std::string).name())<<endl;return 0;}
The cxxdemangle function above can be used to parse the symbol name.
For more information about stacktrace and demangle, see the code of open-source projects such as glog and Google perftools.