为什么每个成员函数都有自己的 .text.* 部分?
Why does each member function get its own .text.* section?
我知道会发生名称重整。我不明白的是:
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 在它自己的部分中,部分名称是该成员函数的错位符号?
我认为这不是链接工作所必需的,因为它是链接时匹配的符号,而不是部分。 IE。如果一切都在 .text 中,它应该可以工作。
有没有办法避免这种情况发生?
不太重复,但请参阅我对 的回答以了解更详细的信息。
g++
(或clang++
)编译a的内联定义
class成员函数如int MyClass::doStuff(int)
作为
弱全局符号的内联定义,例如_ZN7MyClass7doStuffEi
1
每当翻译单元引用该函数时,在目标文件中,
并将这个定义放在它自己的函数部分。
这样做是因为:-
每个翻译中都必须存在内联函数定义
引用函数的单元。但可能会有
链接中的多个目标文件包含相同的
_ZN7MyClass7doStuffEi
.
的定义
所以_ZN7MyClass7doStuffEi
一定是弱的和全局的。 弱 所以
链接器可以自由选择任何一个定义并丢弃
其余的,按照 One Definition Rule 的要求。
全局 以便相同定义中的任何一个
已选择链接 可以 从其他目标文件中引用
在引用它的链接中。
最后每个_ZN7MyClass7doStuffEi
的定义放在
每个目标文件中都有自己的功能部分,以确保
链接器 可以 丢弃此函数定义。如果其他
程序引用的全局符号可以在同一个文件中定义
带有 _ZN7MyClass7doStuffEi
的部分,则可能无法丢弃除一个定义之外的所有定义,从而导致多重定义错误。
[1] 你的评论 "the member function in the test code is not external"
是不正确的。你没有也不能声明成员函数
extern
但是(弱或强)全局符号具有外部链接。
我知道会发生名称重整。我不明白的是:
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 在它自己的部分中,部分名称是该成员函数的错位符号?
我认为这不是链接工作所必需的,因为它是链接时匹配的符号,而不是部分。 IE。如果一切都在 .text 中,它应该可以工作。
有没有办法避免这种情况发生?
不太重复,但请参阅我对
g++
(或clang++
)编译a的内联定义
class成员函数如int MyClass::doStuff(int)
作为
弱全局符号的内联定义,例如_ZN7MyClass7doStuffEi
1
每当翻译单元引用该函数时,在目标文件中,
并将这个定义放在它自己的函数部分。
这样做是因为:-
每个翻译中都必须存在内联函数定义
引用函数的单元。但可能会有
链接中的多个目标文件包含相同的
_ZN7MyClass7doStuffEi
.
所以_ZN7MyClass7doStuffEi
一定是弱的和全局的。 弱 所以
链接器可以自由选择任何一个定义并丢弃
其余的,按照 One Definition Rule 的要求。
全局 以便相同定义中的任何一个
已选择链接 可以 从其他目标文件中引用
在引用它的链接中。
最后每个_ZN7MyClass7doStuffEi
的定义放在
每个目标文件中都有自己的功能部分,以确保
链接器 可以 丢弃此函数定义。如果其他
程序引用的全局符号可以在同一个文件中定义
带有 _ZN7MyClass7doStuffEi
的部分,则可能无法丢弃除一个定义之外的所有定义,从而导致多重定义错误。
[1] 你的评论 "the member function in the test code is not external" 是不正确的。你没有也不能声明成员函数
extern
但是(弱或强)全局符号具有外部链接。