gpt4 book ai didi

c++ - 解开 std::type_info::name 的结果

转载 作者:IT老高 更新时间:2023-10-28 12:01:59 25 4
gpt4 key购买 nike

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

有没有办法从中产生有用的东西?点赞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

在文件 type.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*
指针类型:Derived

在 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() 的调用成功时,返回一个指向本地堆栈分配数组的指针...哎哟!
另请注意,如果您提供缓冲区,abi::__cxa_demangle() 假定它是在堆上分配的。在堆栈上分配缓冲区是一个错误(来自 gnu 文档):“如果 output_buffer 不够长,则使用 realloc 对其进行扩展。” 在指向堆栈的指针上调用 realloc()...哎呀! (另见 Igor Skochinsky 的善意评论。)

您可以轻松验证这两个错误:只需将已接受答案(截至 2013 年 9 月 7 日)中的缓冲区大小从 1024 减小到更小的值,例如 16,并给它命名为 not 长于 15 (因此 realloc() 调用)。尽管如此,根据您的系统和编译器优化,输出将是:垃圾/无/程序崩溃。
要验证第二个错误:将缓冲区大小设置为 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;
}

关于c++ - 解开 std::type_info::name 的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/281818/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com