为什么成员函数的符号很弱?
Why is the symbol of member function weak?
我用 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
Is that C++ specification or decision of GCC?
两者兼而有之。并不是说 C++ 规范处理强符号或弱符号(它没有)。但它确实会影响 GCC 的行为,因为通常扩展会尝试建立在标准的强制行为之上。
当您在 class 主体中定义成员函数时,它自动成为内联函数。在 C++ 语言中,内联函数是可以有多个定义的函数,只要它们出现在不同的翻译单元中即可。这不是问题,因为在 C++ 中,内联函数必须在每个翻译单元(一直到标记序列)中具有完全相同的定义。因此,尽管它们是“不同”的定义,但它们是相同的,因此在某些时候可以简化为一个。
该函数实际上不必在调用站点内联。就C++而言,inline
是关于一个定义规则和链接。因此,根据规范,C::foo
可以有多个定义。
然后你指定__attribute__((noinline))
,所以这个函数不能被物理内联,所以每个TU都必须包含一个函数符号。
这就只剩下一个选择了。符号一定要弱,否则不同翻译单元的不同符号会互相干扰。通过使符号变弱,您可以拥有强制定义并避免物理内联函数,同时维护 C++ 规范。这些不同的符号代表完全相同的功能,因此它们中的任何一个都可以在链接时“获胜”。
我用 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
Is that C++ specification or decision of GCC?
两者兼而有之。并不是说 C++ 规范处理强符号或弱符号(它没有)。但它确实会影响 GCC 的行为,因为通常扩展会尝试建立在标准的强制行为之上。
当您在 class 主体中定义成员函数时,它自动成为内联函数。在 C++ 语言中,内联函数是可以有多个定义的函数,只要它们出现在不同的翻译单元中即可。这不是问题,因为在 C++ 中,内联函数必须在每个翻译单元(一直到标记序列)中具有完全相同的定义。因此,尽管它们是“不同”的定义,但它们是相同的,因此在某些时候可以简化为一个。
该函数实际上不必在调用站点内联。就C++而言,inline
是关于一个定义规则和链接。因此,根据规范,C::foo
可以有多个定义。
然后你指定__attribute__((noinline))
,所以这个函数不能被物理内联,所以每个TU都必须包含一个函数符号。
这就只剩下一个选择了。符号一定要弱,否则不同翻译单元的不同符号会互相干扰。通过使符号变弱,您可以拥有强制定义并避免物理内联函数,同时维护 C++ 规范。这些不同的符号代表完全相同的功能,因此它们中的任何一个都可以在链接时“获胜”。