RTTI与type_info
C++在编译时开启RTTI(Run-Time Type Identification,通过运行时类型识别)特性时,可以在代码中使用typeid操作符(当然还需要包含<typeinfo>),此符号可以对一个变量或者一个类名使用,返回一个type_info对象的引用。编译时会为每种使用到RTTI的特性的C++类都建立一个唯一的type_info对象,并且会包含继承关系,dynamic_cast便是根据这个对象来判断某个基类对象的指针能否向下转换成子类对象的指针。下面为一个使用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
但是我们今天关注的不是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<char>,class std::allocator<char> >
而g++编译执行时返回的却是:
Ss
后者很难理解,因为这是mangle后的符号名,而VC编译器返回的是demangle后的结果。使用C++的类与函数编译成obj文件后,都是使用mangle后的符号名。例如:假如我们编译了某个linux静态库,可以用nm工具查看其内部包含接口的符号(windows下可以使用dumpbin):
nm libmyfunc.a
其会返回许多mangle后的符号名,它们其实就是我们在库中编写的函数接口。
如何将这类符号名转换为可读的名称呢?其实不同编译器都提供了“解析”函数,我们可以如下编码:
#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;
}上面的CxxDemangle函数便可以用来解析符号名。
关于获取stacktrace以及demangle等相关技术可以参看glog、google perftools等相关开源项目的代码。
 
                   
                   
                   
                   
                             本文探讨了C++中RTTI(运行时类型识别)的功能及其应用,特别是typeid操作符和type_info对象的作用。文中详细介绍了如何利用type_info的name()方法获取类型名称,并提供了在不同编译器下解析mangle名称的具体实现。
本文探讨了C++中RTTI(运行时类型识别)的功能及其应用,特别是typeid操作符和type_info对象的作用。文中详细介绍了如何利用type_info的name()方法获取类型名称,并提供了在不同编译器下解析mangle名称的具体实现。
           
       
           
                 
                 
                 
                 
                 
                
               
                 
                 
                 
                 
                
               
                 
                 扫一扫
扫一扫
                     
              
             
                   320
					320
					
 被折叠的  条评论
		 为什么被折叠?
被折叠的  条评论
		 为什么被折叠?
		 
		  到【灌水乐园】发言
到【灌水乐园】发言                                
		 
		 
    
   
    
   
             
            


 
            