c++oding="utf-8" ?>
唯一标准接口是abi::__cxa_demangle,声明于,需手动free返回内存且status为0表示成功;core::demangled_name根本不存在于任何主流实现中,属常见误传。

abi::__cxa_demangle 是唯一可用的标准接口,core::demangled_name 根本不存在
所有主流实现(GCC libstdc++、LLVM libc++、Itanium ABI 规范)里都没有 core::demangled_name。它不是标准函数,也不是跨平台封装,而是对 abi::__cxa_demangle 的拼写误传或私有代码混淆。你搜到的示例代码若调用 core::demangled_name,运行时必报链接错误或编译失败。
- 必须包含
#include,并链接标准 C++ 运行时(通常默认满足) - 函数声明为
char* abi::__cxa_demangle(const char*, char*, size_t*, int*),注意命名空间是abi::,不是core:: - MSVC 完全不提供该函数;Windows 下需改用
UnDecorateSymbolName(dbghelp.h)
传入的 mangled name 不合法是 demangle 失败最常见原因
abi::__cxa_demangle 不做输入校验,只按 Itanium ABI 规则解析。传错格式、截断、含空格、或 MSVC 风格修饰名(如 ??0MyClass@@QEAA@XZ),都会直接返回 nullptr,且 status 可能不变(仍是初始值)。
- 先用命令行验证:
c++filt _Z3fooi应输出foo(int);若报错或原样返回,说明符号本身不可解 - 确保字符串以
_Z开头(普通函数)、_ZN开头(带命名空间/类),且无多余\0、空格或换行 -
status参数必须传地址,不能为nullptr;常见低级错误是写成__cxa_demangle(..., nullptr) - 函数类型无法用
typeid(func).name()获取 mangled 名——这是未定义行为;只能对已知符号字符串解码,或从dladdr+backtrace_symbols中提取
内存管理必须用 free(),且 buf / len 参数组合影响行为
返回的 char* 是 malloc 分配的,必须用 free() 释放。用 delete、delete[] 或栈数组接收会导致未定义行为。
- 推荐用
buf = nullptr+len = nullptr:函数内部分配内存,status == 0时必须free(demangled_name) - 若传入栈缓冲区:
char buf[256]; size_t len = 256;,则len必须初始化,且函数可能因空间不足返回nullptr并把所需最小长度写入len -
status值含义明确:0成功,-1输入非法,-2缓冲区不够,-3内存分配失败
想在日志里打当前函数名?别费劲 demangle,直接用编译器内置宏
运行时动态获取函数名开销大、易出错,而绝大多数调试/日志场景只需当前函数的可读签名。GCC/Clang 支持 __PRETTY_FUNCTION__,MSVC 支持 __FUNCSIG__,它们在编译期展开为已 demangle 的字符串,零成本、零依赖、无内存管理风险。
std::cout 在 GCC/Clang 下输出类似void foo(int, double)- 若需兼容 MSVC,可用预处理器判断:
#ifdef _MSC_VER→__FUNCSIG__,否则用__PRETTY_FUNCTION__ - 这些宏不能用于获取任意函数指针对应的名称,仅限当前作用域;但对日志、断言、性能追踪已足够可靠
实际中最容易被忽略的是:mangled name 不是“随便一个函数地址就能生成”的东西,它本质是链接器视角的符号字符串,必须来自编译器真实生成的符号表条目。试图对普通函数取地址再喂给 abi::__cxa_demangle,基本注定失败。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











