当前位置:  开发笔记 > 编程语言 > 正文

解开std :: type_info :: name的结果

如何解决《解开std::type_info::name的结果》经验,为你挑选了4个好方法。

我目前正在研究一些日志代码,它们应该 - 除其他外 - 打印有关调用函数的信息.这应该相对容易,标准C++有一个type_info类.它包含typeid'd类/函数/ etc的名称.但它被破坏了.它不是很有用.即typeid(std::vector).name()回归St6vectorIiSaIiEE.

有没有办法从中产生有用的东西?就像std::vector上面的例子一样.如果它只适用于非模板类,那也没关系.

该解决方案应该适用于gcc,但如果我可以移植它会更好.这是为了记录所以它不是那么重要,它不能被关闭,但它应该有助于调试.



1> Ali..:

鉴于这个问题/答案得到了关注,以及来自GManNickG的有价值的反馈,我已经清理了一些代码.给出了两个版本:一个具有C++ 11特性,另一个仅具有C++ 98特性.

在文件type.hpp中

#ifndef TYPE_HPP
#define TYPE_HPP

#include 
#include 

std::string demangle(const char* name);

template 
std::string type(const T& t) {

    return demangle(typeid(t).name());
}

#endif

在文件type.cpp中(需要C++ 11)

#include "type.hpp"
#ifdef __GNUG__
#include 
#include 
#include 

std::string demangle(const char* name) {

    int status = -4; // some arbitrary value to eliminate the compiler warning

    // enable c++11 by passing the flag -std=c++11 to g++
    std::unique_ptr res {
        abi::__cxa_demangle(name, NULL, NULL, &status),
        std::free
    };

    return (status==0) ? res.get() : name ;
}

#else

// does nothing if not g++
std::string demangle(const char* name) {
    return name;
}

#endif

用法:

#include 
#include "type.hpp"

struct Base { virtual ~Base() {} };

struct Derived : public Base { };

int main() {

    Base* ptr_base = new Derived(); // Please use smart pointers in YOUR code!

    std::cout << "Type of ptr_base: " << type(ptr_base) << std::endl;

    std::cout << "Type of pointee: " << type(*ptr_base) << std::endl;

    delete ptr_base;
}

它打印:

ptr_base的Base*
类型:指针的类型:Derived

使用g ++ 4.7.2测试,克++ 4.9.0 20140302(实验),铛++ 3.4(躯干184647),铛Linux上的64位3.5(躯干202594)和g ++ 4.7.2(MINGW32的Win32 XP SP2).

如果你不能使用C++ 11的功能,这里是如何在C++ 98中完成的,文件type.cpp现在是:

#include "type.hpp"
#ifdef __GNUG__
#include 
#include 
#include 

struct handle {
    char* p;
    handle(char* ptr) : p(ptr) { }
    ~handle() { std::free(p); }
};

std::string demangle(const char* name) {

    int status = -4; // some arbitrary value to eliminate the compiler warning

    handle result( abi::__cxa_demangle(name, NULL, NULL, &status) );

    return (status==0) ? result.p : name ;
}

#else

// does nothing if not g++
std::string demangle(const char* name) {
    return name;
}

#endif


(2013年9月8日更新)

接受答案(如2013年9月7日的),当调用abi::__cxa_demangle()成功,返回一个指针到本地,堆栈分配数组 ...哎哟!
另请注意,如果提供缓冲区,则abi::__cxa_demangle()假定它在堆上分配.在堆栈上分配的缓冲区(从GNU DOC)的错误:"如果output_buffer没有足够长的时间,它是使用扩展realloc." 调用realloc()指向堆栈的指针 ......哎哟!(另见Igor Skochinsky的善意评论.)

你可以很容易地验证这两种错误的:是从1024减少缓冲区大小,以接受的答案(如2013年9月7日),以更小的东西,例如16,并给它一个名字的东西超过15(因此realloc()叫).仍然,根据您的系统和编译器优化,输出将是:garbage/nothing/program crash.
要验证第二个错误:将缓冲区大小设置为1并使用名称长度超过1个字符的内容调用它.当你运行它时,程序几乎肯定会在尝试realloc()使用指向堆栈的指针进行调用时崩溃.


(2010年12月27日的旧答案)

对KeithB代码进行的重要更改:缓冲区必须由malloc分配或指定为NULL.不要在堆栈上分配它.

检查这种状态也是明智之举.

我没找到HAVE_CXA_DEMANGLE.我检查__GNUG__虽然不能保证代码甚至可以编译.谁有更好的主意?

#include 

const string demangle(const char* name) {

    int status = -4;

    char* res = abi::__cxa_demangle(name, NULL, NULL, &status);

    const char* const demangled_name = (status==0)?res:name;

    string ret_val(demangled_name);

    free(res);

    return ret_val;
}


来自[docs](http://idlebox.net/2008/0901-stacktrace-demangled/cxa_demangle.htt):`output_buffer`一个内存区域,用malloc分配,长度为*length bytes,其中demangled名称为存储.如果output_buffer不够长,则使用realloc进行扩展.output_buffer可能改为NULL; 在这种情况下,demangled名称放在使用malloc分配的内存区域中.
@IgorSkochinsky是的,我之前的评论中有一个拼写错误,但我无法编辑.我想写的是:"上次我检查了'abi :: __ cxa_demangle`,希望它在堆上分配**.**"非常感谢您查找文档!
如果使用`std :: unique_ptr `作为指针的签名可能会更清楚.

2> moof2k..:

Boost核心包含一个demangler.结帐core/demangle.hpp:

#include 
#include 
#include 

template struct X
{
};

int main()
{
    char const * name = typeid( X ).name();

    std::cout << name << std::endl; // prints 1XIiE
    std::cout << boost::core::demangle( name ) << std::endl; // prints X
}

它基本上只是一个包装器abi::__cxa_demangle,正如之前所建议的那样.



3> KeithB..:

这就是我们使用的.HAVE_CXA_DEMANGLE仅在可用时设置(仅限最新版本的GCC).

#ifdef HAVE_CXA_DEMANGLE
const char* demangle(const char* name)
{
   char buf[1024];
    unsigned int size=1024;
    int status;
    char* res = abi::__cxa_demangle (name,
                                 buf,
                                 &size,
                                 &status);
    return res;
  }
#else
const char* demangle(const char* name)
{
  return name;
}
#endif  


警告!上面的代码可能会导致程序崩溃.缓冲区必须由malloc分配或指定为NULL.不要在堆栈上分配它.请参阅下面的代码.
你需要包含`#include `.

4> Johannes Sch..:

在这里,看一下type_strings.hpp,它包含一个可以完成你想要的功能.

如果您只是寻找一个demangling工具,您可以使用它来破坏日志文件中显示的内容,请查看c++filtbinutils附带的内容.它可以解析C++和Java符号名称.


链接到type_strings.cpp似乎坏了.
推荐阅读
家具销售_903
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有