添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

C 和 C++ 程序中的函数、数据和对象均在内部由其修饰名表示。 “修饰名” 是编译器在编译对象、数据或函数定义期间创建的编码字符串。 它记录名称以及调用约定、类型、函数参数和其他信息。 此名称修饰(也称为“名称重整” )可帮助链接器在链接可执行文件时查找正确的函数和对象。

修饰的命名约定在各种版本的 Visual Studio 中有所不同,并且可能在不同的目标体系结构上也不同。 若要正确链接使用 Visual Studio、C 和 C++ 创建的源文件,应使用相同的编译器工具集、标志和目标体系结构编译 DLL 和库。

通过 Visual Studio 2022,Visual Studio 2015 或更高版本生成的库可由使用更高版本的 Visual Studio 生成的应用程序使用。 有关详细信息,请参阅 Visual Studio 版本之间的 C++ 二进制兼容性

使用修饰名

通常情况下,无需知道修饰名也可编写已成功编译和链接的代码。 修饰名是编译器和链接器内部的实现详细信息。 通常,这些工具可以处理未修饰形式的名称。 但是,在向链接器和其他工具指定函数名时,有时则需要修饰名。 例如,若要匹配重载的 C++ 函数、命名空间成员、类构造函数、析构函数和特殊成员函数,则必须指定修饰名。 有关选项标志和其他需要修饰名的情形的详细信息,请参阅正在使用的工具和选项的相关文档。

如果你更改函数名、类、调用约定、返回类型或任何参数,则修饰名也会改变。 在这种情况下,你必须获取新的修饰名,并将其用于指定了修饰名的任何位置。

在链接到用其他编程语言编写的或使用其他编译器的代码时,名称修饰也很重要。 编译器不同,则使用名称修饰约定不同。 在可执行文件链接到用另一种语言编写的代码时,必须特别留意将导出和导入的名称与调用约定相匹配。 程序集语言代码必须使用 MSVC 修饰名和调用约定来链接到使用 MSVC 编写的源代码。

C++ 修饰名的格式

C + + 函数的修饰名包含以下信息:

  • 函数名称。

  • 函数所属的类(如果该函数为成员函数)。 修饰可能包括含有函数所属的类的类,等等。

  • 函数所属的命名空间(如果该函数是命名空间的一部分)。

  • 函数参数的类型。

  • 调用约定。

  • 函数的返回类型。

  • 可选的目标特定元素。 在 ARM64EC 对象中,名称中会插入 $$h 标记。

    修饰名中编码有函数名和类名。 修饰名的其余部分是具有仅用于编译器和链接器的内部意义的代码。 以下示例介绍的是未修饰和修饰的 C++ 名称。

    对于具有 C 链接的 ARM64EC 函数(无论是编译为 C 还是通过使用 extern "C" ),修饰名前会预置 #

    查看修饰名

    在编译包含数据、对象或者函数定义或原型的源文件之后,可以获取符号名称的修饰形式。 若要检查你的程序中的修饰名,可以使用以下方法之一:

    若要使用列表查看修饰名

  • 生成列表的方式如下:将 /FA (列出文件类型) 编译器选项设置为带源代码的程序集 ( /FAs ),从而编译包含数据、对象或者函数定义或原型的源文件。

    例如,在开发人员命令提示符处输入 cl /c /FAs example.cpp 以生成列表文件 example.asm

  • 在生成的列表文件中,找到以 PUBLIC 开头、分号 ( ; ) 结尾且后接未修饰的数据或函数名的行。 PUBLIC 和分号之间的符号即为修饰名。

    若要使用 DUMPBIN 查看修饰名

  • 若要在 OBJ 或 LIB 文件中查看导出的符号,请在开发人员命令提示符处输入 dumpbin /exports <obj-or-lib-file>

  • 若要查找符号的修饰形式,请查找括号中的未修饰名。 修饰名位于同一行中,在未修饰名之前。

    查看未修饰名

    可以使用 undname.exe 将修饰名转换为其未修饰形式。 此示例演示其工作原理:

    C:\>undname ?func1@a@@AAEXH@Z
    Microsoft (R) C++ Name Undecorator
    Undecoration of :- "?func1@a@@AAEXH@Z"
    is :- "private: void __thiscall a::func1(int)"
    

    其他 MSVC 生成工具
    使用 extern 指定链接

  •