我知道发生名称修改的情况。我不明白的是:
class MyClass{
public:
int doStuff(int a){
return a+1;
}
};
int main(){
MyClass myclass;
myclass.doStuff(2);
return 0;
}
> g++ -c -O0 blah.cpp && objdump -h blah.o
blah.o: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .group 00000008 0000000000000000 0000000000000000 00000040 2**2
CONTENTS, READONLY, EXCLUDE, GROUP, LINK_ONCE_DISCARD
1 .text 00000043 0000000000000000 0000000000000000 00000048 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
2 .data 00000000 0000000000000000 0000000000000000 0000008b 2**0
CONTENTS, ALLOC, LOAD, DATA
3 .bss 00000000 0000000000000000 0000000000000000 0000008b 2**0
ALLOC
4 .text._ZN7MyClass7doStuffEi 00000013 0000000000000000 0000000000000000 0000008c 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
5 .comment 00000036 0000000000000000 0000000000000000 0000009f 2**0
CONTENTS, READONLY
6 .note.GNU-stack 00000000 0000000000000000 0000000000000000 000000d5 2**0
CONTENTS, READONLY
7 .eh_frame 00000058 0000000000000000 0000000000000000 000000d8 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
为什么MyClass.doStuff在其自己的部分中,部分名称是该成员函数的错误符号?
我认为这对于链接工作不是必需的,因为它是链接时匹配的符号,而不是节。即。如果所有内容都在.text中,则它应该可以工作。
有没有办法使这种情况不发生?
不是完全重复,但请参阅我对this related question的答复以了解更多详细信息。
g++
(或clang++
)编译a的内联定义类成员函数,例如int MyClass::doStuff(int)
作为弱全局符号的内联定义,例如_ZN7MyClass7doStuffEi
1在目标文件中,只要翻译单元引用该函数,并将此定义放在其自己的功能部分。
之所以这样做是因为:-
每个翻译中必须存在一个内联函数定义引用功能的单位。但是可能有链接中包含相同对象的多个目标文件_ZN7MyClass7doStuffEi
的定义。
因此_ZN7MyClass7doStuffEi
必须是弱势且全局的。 弱所以链接器可以自由选择任何一个定义并丢弃其余的,按One Definition Rule的要求。Global,因此无论是相同定义之一从其他对象文件中引用为链接can选择的对象在确实引用它的链接中。
最后将_ZN7MyClass7doStuffEi
的每个定义放在每个目标文件中都有自己的功能部分,以确保链接器can放弃此函数定义。如果其他程序引用的全局符号可以在相同的位置定义_ZN7MyClass7doStuffEi
部分,则可能无法舍弃一个定义,而导致多定义错误。
extern
,但是(弱或强)全局符号具有外部链接。