为什么每个成员函数都有自己的 .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)作为 弱全局符号的内联定义,例如_ZN7MyClass7doStuffEi1 每当翻译单元引用该函数时,在目标文件中, 并将这个定义放在它自己的函数部分。

这样做是因为:-

每个翻译中都必须存在内联函数定义 引用函数的单元。但可能会有 链接中的多个目标文件包含相同的 _ZN7MyClass7doStuffEi.

的定义

所以_ZN7MyClass7doStuffEi一定是弱的和全局的。 所以 链接器可以自由选择任何一个定义并丢弃 其余的,按照 One Definition Rule 的要求。 全局 以便相同定义中的任何一个 已选择链接 可以 从其他目标文件中引用 在引用它的链接中。

最后每个_ZN7MyClass7doStuffEi的定义放在 每个目标文件中都有自己的功能部分,以确保 链接器 可以 丢弃此函数定义。如果其他 程序引用的全局符号可以在同一个文件中定义 带有 _ZN7MyClass7doStuffEi 的部分,则可能无法丢弃除一个定义之外的所有定义,从而导致多重定义错误。


[1] 你的评论 "the member function in the test code is not external" 是不正确的。你没有也不能声明成员函数 extern 但是(弱或强)全局符号具有外部链接。