我只是想知道为什么名称修饰从未被 C++ 标准标准化。显然,拥有不同的名称修饰算法会损害互操作性[1],而且我看不出让它实现定义的任何优势。
也就是说,与调用约定或原语大小相反,机器本身并不关心甚至不知道函数是如何被调用的。那么为什么它没有标准化,为什么它仍然没有标准化呢?编译器在过去无论如何都更改了版本之间的规则。
[1] 所有那些将功能输出为extern "C"
说话量的人。
我只是想知道为什么名称修饰从未被 C++ 标准标准化。显然,拥有不同的名称修饰算法会损害互操作性[1],而且我看不出让它实现定义的任何优势。
也就是说,与调用约定或原语大小相反,机器本身并不关心甚至不知道函数是如何被调用的。那么为什么它没有标准化,为什么它仍然没有标准化呢?编译器在过去无论如何都更改了版本之间的规则。
[1] 所有那些将功能输出为extern "C"
说话量的人。
该标准不涉及实施细节。有很多很多的事情取决于实现,并且会阻止程序一起工作:类的布局方式, 的结构vtable
等。通常,如果编译器更改其中任何一个,编译器就会更改名称修饰。这是有意的,因为它可以防止无法链接的代码。
给定平台可以定义 C++ ABI;所有遵循它的编译器都将使用兼容的实现,并具有通用名称修饰。然而,这对平台供应商来说是一个问题;无论出于何种原因,很少有供应商定义了 C++ ABI。
之所以extern "C"
有效,是因为几乎所有平台都定义了 C ABI。
该标准实际上并不需要名称修饰。就此而言,该标准不需要 IEEE 浮点数或任何其他东西。
在它可以依赖广泛的 ABI 之前, GCC 实际上已经竭尽全力使用与其竞争对手不同的名称修改方案:
G++ 不像其他 C++ 编译器那样进行名称修改。这意味着用一个编译器编译的目标文件不能与另一个编译器一起使用。
这种效果是有意的,可以保护您免受更微妙的问题的影响。编译器在 C++ 实现的许多内部细节方面存在差异,包括:类实例的布局方式、多重继承的实现方式以及虚函数调用的处理方式。如果名称编码相同,您的程序将链接到其他编译器提供的库 - 但程序在运行时会崩溃。然后在链接时而不是在运行时检测不兼容的库。
名称修改也比许多程序员意识到的要复杂。例如,标准如何为 C++ 可以运行的所有平台指定可接受的调用约定?stdcall
即使 RISC 系统通常在寄存器而不是堆栈中传递参数,是否应该要求 RISC 系统支持 x86 ?