从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
答案 0 :(得分:5)
我确信这个决定是务实的,以避免对预先存在的C连接器进行任何更改(很可能甚至来自cfront)。通过使用相同的字符集发出符号,使用C链接器,您不必进行任何数量的更新,并且可以使用现成的链接器。
此外,C和C ++是广泛可移植语言,他们不希望冒险通过包含意外符号来破坏更加模糊的二进制格式(可能在嵌入式系统上)。
最后因为你总是可以解码(例如gc++filt
之类的东西),所以使用全文表示似乎不值得。
P.S。您绝对不希望在函数名称中包含参数名称:如果重命名参数会破坏ABI,人们将不会高兴。已经很难保持ABI兼容性。
答案 1 :(得分:1)
答案 2 :(得分:1)
GCC符合Itanium C++ ABI。如果您的问题是“为什么Itanium C ++ ABI要求名称被破坏?”那么答案可能是
关于第二点,在Ulrich Drepper的文章How To Write Shared Libraries中有一个很好的解释。
答案 3 :(得分:1)
你基本上回答了自己的问题:
合法名称的一般正则表达式与
[\w_](\w\d_)*
类似。
从一开始,C ++就使用了预先存在的(C)链接器/加载器技术。任何关于ld
,ld-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 ++格式没有任何好处。这个东西应该针对机器进行优化。为什么你会让它不那么适合机器,以使其更适合人类?并且可能在后者失败的同时也是如此。
您说您的编译器不会发出“原始符号”。我认为确实如此。