我如何在MSVC中取消名称?gcc中有abi :: __ cxa_demangle函数.在MSDN中我找到了UnDecorateSymbolName:
http://msdn.microsoft.com/ru-ru/library/windows/desktop/ms681400%28v=vs.85%29.aspx
不幸的是,这个功能甚至不能解开这样的符号:
#include <Windows.h>
#include <DbgHelp.h>
#include <cstdlib>
#include <iostream>
#include <typeinfo>
int main()
{
SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
if (!SymInitialize(GetCurrentProcess(), NULL, TRUE))
{
std::cout << "SymInitialize returned error: " << GetLastError() << '\n';
return EXIT_FAILURE;
}
class Foo {};
Foo instance;
const char* decorated_name = typeid(instance).name();
char undecorated_name[1024];
if (!UnDecorateSymbolName(decorated_name, undecorated_name, sizeof(undecorated_name) / sizeof(*undecorated_name), UNDNAME_COMPLETE))
{
std::cout << "UnDecorateSymbolName returned error: " << GetLastError() << '\n';
return EXIT_FAILURE;
}
std::cout << "Decorated name: " << decorated_name << '\n'
<< "Undecorated name: " << undecorated_name << '\n';
}
Run Code Online (Sandbox Code Playgroud)
产量
装饰名称:?AVFoo @?4?main @
简单的名字:?AVFoo @?4?main @
如果我做错了?
我听说过关于_unDName函数的某个地方,但我找不到它的任何例子.在哪个头文件中定义?
zha*_*fei 14
Visual Studio已经发布了一个名为undname的实用程序.对于我的VS2010和VS2013安装,它安装在%VSINSTALL%\ vc\bin目录中.对于x64平台,在%VSINSTALL%\ vc\amd64\bin目录中.
示例用法是:
D:\work\VS2013>undname "?static_x@?1??getX@@YAAAUX@@XZ@4U2@A"
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.
Undecoration of :- "?static_x@?1??getX@@YAAAUX@@XZ@4U2@A"
is :- "struct X `struct X & __cdecl getX(void)'::`2'::static_x"
Run Code Online (Sandbox Code Playgroud)
获取demangled名称的另一种方法是使用/ FAsc /FAyour_source.asm编译器选项,它将生成汇编列表,其中每个错位名称都使用它的demangled名称进行评论.请参阅此链接以供参考.
小智 7
Visual Studio 2019 更新。
(1) typeid(instance).name() - 在请求中使用 - 已经返回未修饰的名称:在这种情况下不需要进一步的整理
(2) 即使我们去掉最初的点,bin 文件夹中提供的命令 UNDNAME.EXE 也无法正常工作。例如,“.?AVFoo@?1??main@@YAHXZ@”被分解为“?? int __cdecl main(void)'::2'::AVFoo”,给出了无效的名称 AVFoo。正确的名字必须是 Foo
(3) dbghelp API UnDecorateSymbolName() 也不起作用
(4) 从编译器为指令 typeid() 生成的程序集中可以推导出正确的代码
这是一个小程序,它将正确地取消修饰所有 C++ 损坏的符号:
// compile as: cl -W3 und.c
#include <windows.h>
#include "dbghelp.h"
#include <stdio.h>
#pragma comment(lib, "dbghelp.lib")
extern char *__unDName(char*, const char*, int, void*, void*, int);
int
main(int argc, char **argv)
{
const char *decorated_name = 0;
char undecorated_name[1024];
if (argc == 2) decorated_name = argv[1];
else {
printf("usage: %s <decorated_name>\n", argv[0]);
return 1;
}
__unDName(undecorated_name, decorated_name+1, 1024, malloc, free, 0x2800);
printf("Decorated name: %s\n", decorated_name);
printf("Undecorated name: %s\n", undecorated_name);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
例如:
和“.?AVFoo@?1??main@@YAHXZ@”
装饰名:.?AVFoo@?1??main@@YAHXZ@
未修饰的名称:class
int __cdecl main(void)'::2'::Foo
似乎UndecorateSymbolName/ __unDName不能处理函数本地名称.如果将类定义移动到全局范围,.name()则将返回已经为demangled的名称(用于.raw_name()获取受损的名称).
要手动解压缩(全局)原始名称,您需要对代码进行两处更改:
1)跳过错位名称中的前导句点(即从中开始'?').
2)而不是0,使用标志值0x2800(UNDNAME_32_BIT_DECODE | UNDNAME_TYPE_ONLY).
我从VS2012的CRT来源发现了这个:
if ((pTmpUndName = __unDName(NULL, (this->_M_d_name)+1, 0,
&_malloc_base, &_free_base,
UNDNAME_32_BIT_DECODE | UNDNAME_TYPE_ONLY)) == NULL)
Run Code Online (Sandbox Code Playgroud)