为什么g ++不生成“原始”符号?

时间:2015-08-10 14:34:21

标签: c++ name-mangling

从C我们知道什么是合法变量名称。合法名称的一般正则表达式类似于[\w_](\w\d_)*

使用dlsym我们可以加载任意字符串,C++ mangles names that include @ in the ABI.

我的问题是:可以使用任意字符串吗?关于dlsym的文档似乎没有提及任何内容。

出现的

Another question似乎意味着完全可以使用任意以null结尾的符号。这要求我提出以下问题:

为什么g ++不会发出带有名称和参数列表的原始函数签名,包括名称空间和类成员资格?

这就是我的意思:

namespace test {
class A
{
    int myFunction(const int a);
};
}

namespace test {
int A::myFunction(const int a){return a * 2;}
}

不会编译到

int ::test::A::myFunction(const int a)\0

相反,它使用g ++ 4.9.2 -

编译到我的64位机器上
0000000000000000 T _ZN4test1A10myFunctionEi

此输出由nm读取。代码是使用g++ -c test.cpp -o out

编译的

5 个答案:

答案 0 :(得分:5)

我确信这个决定是务实的,以避免对预先存在的C连接器进行任何更改(很可能甚至来自cfront)。通过使用相同的字符集发出符号,使用C链接器,您不必进行任何数量的更新,并且可以使用现成的链接器。

此外,C和C ++是广泛可移植语言,他们不希望冒险通过包含意外符号来破坏更加模糊的二进制格式(可能在嵌入式系统上)。

最后因为你总是可以解码(例如gc++filt之类的东西),所以使用全文表示似乎不值得。

P.S。您绝对不希望在函数名称中包含参数名称:如果重命名参数会破坏ABI,人们将不会高兴。已经很难保持ABI兼容性。

答案 1 :(得分:1)

  1. 由于链接器强加的导出名称的限制(包括操作系统的动态链接器) - 字符集,长度。因此而very phenomenon of mangling出现了。
    • 推论:在存在这些限制的媒体中(各种使用自己的链接器的虚拟机:例如.NET,Java),修复也不存在。
  2. 生成与其他导出不兼容的导出的每个编译器必须使用不同的方案。因为链接器(静态或动态)并不关心ABI,所以它关心的只是标识符。

答案 2 :(得分:1)

GCC符合Itanium C++ ABI。如果您的问题是“为什么Itanium C ++ ABI要求名称被破坏?”那么答案可能是

  1. 因为它的设计师认为这是一个好主意和
  2. 较短的符号可用于较小的目标文件和更快的动态链接。
  3. 关于第二点,在Ulrich Drepper的文章How To Write Shared Libraries中有一个很好的解释。

答案 3 :(得分:1)

你基本上回答了自己的问题:

  

合法名称的一般正则表达式与[\w_](\w\d_)*类似。

从一开始,C ++就使用了预先存在的(C)链接器/加载器技术。任何关于ldld-linux.so等的“C ++”都没有。

因此,链接仅限于C中的合法内容。这不包括冒号,括号,&符号,星号,以及用纯文本编码C ++标识符所需的任何其他内容。

答案 4 :(得分:1)

(在这个答案中,我忽略了你在::test::A::void myFunction(const int a)的例子中犯了几个拼写错误。

此格式为:

  • 不是程序员特定的;考虑到所有这些是相同的,为什么混淆了人们:
    • int ::test::A::myFunction(const int)
    • int ::test::A::myFunction(int const)
    • int test::A::myFunction(int const)
    • int test :: A :: myFunction (int const)
    • 等......
  • 明确的
  • 简洁;没有参数名称或其他不必要的装饰
  • 更容易解析(注意每个组件的长度以数字形式出现)

与此同时,我认为为C ++ ABI选择人类可读的外观类似C ++格式没有任何好处。这个东西应该针对机器进行优化。为什么你会让它不那么适合机器,以使其更适合人类?并且可能在后者失败的同时也是如此。

您说您的编译器不会发出“原始符号”。我认为确实如此。