成员函数符号为什么是弱符号?

6

我使用 g++ (7.3.0) 编译了这段 C++ 代码。

struct C {
  __attribute__((noinline)) int foo() { return 0; };
};

int bar(C &c) { return c.foo(); }

我使用nm发现foo是弱引用,这是由于C++规范还是GCC的决定导致的?

实验流程:

$ g++ test.cpp -c -Og  
$ nm test.o  
0000000000000000 T _Z3barR1C  
0000000000000000 W _ZN1C3fooEv

1
请您提供编译文件所用的命令行,并发布nm的输出结果。我发现bar是弱符号,而不是foo - KamilCuk
@ KamilCuk,抱歉我把它们搞混了。 - eddie kuo
据我所知,weak 不是标准规定的内容;它是一种实现细节。 - bolov
1个回答

10
这既是C++规范的要求,也是GCC的决定。虽然C++规范没有涉及强符号或弱符号的处理(它并没有),但它确实会影响GCC的行为,因为通常扩展会尝试建立在标准规定的行为之上。
在类体中定义成员函数时,它自动成为内联函数。在C++语言中,内联函数是可以有多个定义的函数,只要它们出现在不同的翻译单元中即可。这不是问题,因为在C++中,内联函数在每个翻译单元中必须具有完全相同的定义(到标记序列)。因此,即使它们是“不同”的定义,它们也是相同的,并且可以在某个时刻简化为单一的定义。
函数不必实际上在调用点进行内联。就C++而言,inline关键字与一次定义规则和链接有关。当你拥有这些时,根据规范可能有多个C::foo的定义。
然后你指定了__attribute__((noinline)),这样函数就无法被物理内联,因此每个TU必须包含该函数的符号。
这只剩下一种选择。该符号必须是弱符号,否则不同翻译单元中的不同符号将互相干扰。通过使符号为弱符号,您可以拥有必需的定义并避免物理内联该函数,同时保持符合C++规范。这些不同的符号代表完全相同的函数,因此在链接时任何一个符号都可以“胜出”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接