GCC生成的符号名称的还原-demangle方法

在C++中,GCC编译器生成的符号名称(符号名修饰,或者mangled names)直接输出,阅读起来比较费劲,因为GCC为了保证每个类型或者函数的唯一性,按照特定方式生成了符号名称,有时我们需要查询到这些名称的含义时,往往比较复杂,不过好在cxxabi.h库提供了__cxa_demangle方法,可以将符号名称还原为人类可读的方式,例如将NSt3__115__bit_referenceINS_6vectorIbNS_9allocatorIbEEEELb1EEE符号名称还原为_Bit_reference

你也可以使用GUN提供的c++filt,这也可以解决该问题,并且更加简便。在安装有GUN工具链的terminal上执行如下命令。

c++filt "mangledName"

示例:

[wuqiling@macos] c++filt "_Z3fooi"
foo(int)

如下是还原方法:

// demangle 函数接收一个 mangle 名称,并返回解码后的名称。
std::string demangle(const char* mangled_name) {
    int status = 0;
    std::unique_ptr<char, void(*)(void*)> demangled_name(
        abi::__cxa_demangle(mangled_name, nullptr, nullptr, &status),
        std::free
    );
    return (status == 0) ? demangled_name.get() : mangled_name;
}

_cxa_demangle函数

char* abi::__cxa_demangle(const char* mangled_name, char* output_buffer, size_t* length, int* status);

参数说明

  • mangled_name: 要解码的符号名称。

  • output_buffer: 解码后的名称存储的缓冲区。如果为 nullptr,函数将分配足够的内存来存储解码后的名称。

  • length: 指向输出缓冲区大小的指针。如果 output_buffernullptr,函数将忽略此参数。

  • status: 指向整数的指针,用于返回解码操作的状态,如下是参数含义:

    • 0: 解码成功。

    • -1: 输入不是有效的修饰名称。

    • -2: 内存分配失败。

    • -3: 未知的错误。

演示代码

#include <cxxabi.h>
#include <iostream>
#include <memory>
#include <string>
#include <typeinfo>
#include <vector>
using namespace std;

class Base {
   public:
    virtual float f() { return 1.0; }
    virtual ~Base() {}
};

class Derived : public Base {};

string demangle(const char* mangled_name) {
    int status = 0;
    unique_ptr<char, void (*)(void*)> demangled_name(
        abi::__cxa_demangle(mangled_name, nullptr, nullptr, &status), free);
    return (status == 0) ? demangled_name.get() : mangled_name;
}

int main() {
    Base* p = new Derived;
    const char* name = typeid(p).name();

    vector<bool> arr{1, 0, 1, 0, 1, 0, 1};
    bool a = arr[0];
    auto b = arr[0];

    cout << "before:\n";
    cout << "type name: " << name << endl;
    cout << "type vector<string>: " << typeid(vector<string>).name() << endl;
    cout << "type a: " << typeid(a).name() << "\ntype b: " << typeid(b).name()
         << endl;
    cout << "\nafter:\n";
    cout << "type name: " << demangle(name) << endl;
    cout << "type vector<string>: " << demangle(typeid(vector<string>).name()) << endl;
    cout << "type a: " << demangle(typeid(a).name())
         << "\ntype b: " << demangle(typeid(b).name()) << endl;

    return 0;
}
before:
type name: P4Base
type vector<string>: St6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE
type a: b
type b: St14_Bit_reference

after:
type name: Base*
type vector<string>: std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >
type a: bool
type b: std::_Bit_reference
作者:WuQiling
文章链接:https://www.wqlblog.cn/gcc生成的符号名称的还原-demangle方法/
文章采用 CC BY-NC-SA 4.0 协议进行许可,转载请遵循协议
暂无评论

发送评论 编辑评论


				
默认
贴吧
上一篇
下一篇