c – 解除std :: type_info :: name的结果

我目前正在处理一些日志代码,除其他外,打印关于调用函数的信息。这应该比较容易,标准C有一个type_info类。这包含了typeid的类/函数/等的名称。但它的损坏。这不是很有用。也就是说typeid(std :: vector< int>)。name()返回St6vectorIiSaIiEE。

有没有办法生产一些有用的东西? like std :: vector< int>对于上面的例子。如果它只适用于非模板类,那也很好。

解决方案应该为gcc工作,但它会更好,如果我可以移植它。它用于日志记录,所以它不那么重要,它不能关闭,但它应该有助于调试。

考虑到这个问题/答案收到的关注,以及从GManNickG的宝贵反馈,我已经清理了一点代码。提供了两个版本:一个具有C 11特征,另一个具有仅C 98特征。

在文件type.hpp

#ifndef TYPE_HPP
#define TYPE_HPP

#include <string>
#include <typeinfo>

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

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

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

#endif

在文件类型cpp(要求C 11)

#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>

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<char, void(*)(void*)> 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 <iostream>
#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 *
委托类型:派生

在Linux 64位和g 4.7.2(Mingw32,Win32 XP SP2)上用g 4.7.2,g 4.9.0 20140302(实验),clang 3.4(主干184647),clang 3.5(主干202594)测试。

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

#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>

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日)

The accepted answer (as of Sep 7, 2013),当调用abi :: __ cxa_demangle()成功时,返回一个指向本地,堆栈分配的数组的指针… ouch!
还要注意,如果你提供一个缓冲区,abi :: __ cxa_demangle()假定它被分配在堆上。在堆栈上分配缓冲区是一个错误(来自gnu doc):“如果output_buffer不够长,则使用realloc进行扩展。调用realloc()在指向堆栈的指针…哎哟! (另见Igor Skochinsky的类型评论。)

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

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

KeithB’s code所做的重要更改:缓冲区必须由malloc分配或指定为NULL。不要在堆栈上分配它。

明智的做法是检查状态。

我找不到HAVE_CXA_DEMANGLE。我检查__GNUG__虽然这不保证代码甚至编译。任何人都有一个更好的主意?

#include <cxxabi.h>

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;
}
http://stackoverflow.com/questions/281818/unmangling-the-result-of-stdtype-infoname

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c – 解除std :: type_info :: name的结果