我有一个源文件,为一个非常大的类定义了移动构造函数。我在Linux系统上使用g++ 4.9.2进行编译。当我转储ELF目标文件的符号表时,我看到移动构造函数有两个列表。这两个列表具有相同的地址、大小和类型,并且链接器可以正常链接它,没有违反ODR。当我反汇编目标文件时,我只看到一个移动构造函数。我的结论是符号表有两个指向同一位置的条目。
对于此特定类的构造函数(也是在同一源文件中定义的),同样会出现这种行为。
我唯一看到的不太明白的编译标志是“-m64”,但我不知道这会如何影响符号表。
我还尝试使用g++ 9.2.0,现在符号表中有3个条目!其中两个指向相同的地址,第三个指向地址0x0,在.text.unlikely部分,并标记为[clone .cold]。
这是为什么呢?
编辑:实际上,我可以用一个非常小的类在家里重现这个问题。
对于此特定类的构造函数(也是在同一源文件中定义的),同样会出现这种行为。
我唯一看到的不太明白的编译标志是“-m64”,但我不知道这会如何影响符号表。
我还尝试使用g++ 9.2.0,现在符号表中有3个条目!其中两个指向相同的地址,第三个指向地址0x0,在.text.unlikely部分,并标记为[clone .cold]。
这是为什么呢?
编辑:实际上,我可以用一个非常小的类在家里重现这个问题。
// class.h
class VeryLargeClass
{
int data;
public:
VeryLargeClass(VeryLargeClass&&);
};
// class.cpp
#include "class.h"
VeryLargeClass::VeryLargeClass(VeryLargeClass&& other)
{
data = other.data;
other.data = 0;
}
如果我使用 g++ -c -O3 class.cpp -o class.o
编译它,然后用 objdump -t class.o | c++filt
转储符号表,我得到以下结果:
class.o:文件格式为elf64-x86-64。
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 main.cc
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 g F .text 000000000000000b VeryLargeClass::VeryLargeClass(VeryLargeClass&&)
0000000000000000 g F .text 000000000000000b VeryLargeClass::VeryLargeClass(VeryLargeClass&&)
注意移动构造函数在符号表中出现了两次?我猜我对ELF格式有些不理解。这是使用g++ 10.2完成的。