为什么链接器报告全局函数的乘法定义符号,而不是类静态方法
Why does the linker report a multiply defined symbol for global functions but not class static methods
我知道有时链接器不会注意到在提供给链接器的所有输入(.obj 文件和静态 .lib 文件(中多次定义了符号。 当然,有时链接器确实会注意到一个符号被定义了两次并给出错误。
但在下面的代码中,链接器确实注意到全局函数定义了两次,同时没有注意到类静态方法定义了两次。 其他一切都是平等的。
这正常吗? 有解释吗? 同样,我知道链接器有时永远不会注意到第二个符号定义。 问题是全局函数和类静态方法在多次定义链接器和符号方面有什么区别。
感谢您抽出宝贵时间提供帮助。 如果我了解这里发生的事情,我会感觉更好。 下面是三个编译并链接在一起的源文件。
翻译单元1.cpp:
// First definition of GlobalFunc()
void GlobalFunc() {std::cout << "GlobalFunc() in Translation Unit 1" << std::endl;}
void GlobalFunc_TransUnit1() {GlobalFunc();}
struct Foo
{
// First definition of Foo::ClassStaticFunc()
static void ClassStaticFunc() {std::cout << "Foo::ClassStaticFunc() in Translation Unit 1" << std::endl;}
};
void ClassStaticFunc_TransUnit1() {Foo::ClassStaticFunc();}
翻译单元2.cpp:
// Second definition of GlobalFunc()
void GlobalFunc() {std::cout << "GlobalFunc() in Translation Unit 2" << std::endl;}
void GlobalFunc_TransUnit2() {GlobalFunc();}
struct Foo
{
// Second definition of Foo::ClassStaticFunc()
static void ClassStaticFunc() {std::cout << "Foo::ClassStaticFunc() in Translation Unit 2" << std::endl;}
};
void ClassStaticFunc_TransUnit2() {Foo::ClassStaticFunc();}
main.cpp - 从输出中我们可以知道哪个定义被调用
void GlobalFunc_TransUnit1();
void GlobalFunc_TransUnit2();
void ClassStaticFunc_TransUnit1();
void ClassStaticFunc_TransUnit2();
int main(int argc, char** argv)
{
// This won't link (as expected).
// The linker reports that GlobalFunc() is defined twice.
GlobalFunc_TransUnit1();
GlobalFunc_TransUnit2();
// This links despite Foo::ClassStaticFunc() being defined twice.
// In the final executable, both ClassStaticFunc_TransUnit1() and
// ClassStaticFunc_TransUnit2() call the same Foo::ClassStaticFunc() -
// which happens to be the definition in TranslationUnit1.cpp
ClassStaticFunc_TransUnit1(); // Calls Foo::ClassStaticFunc() in TranslationUnint1.cpp
ClassStaticFunc_TransUnit2(); // Also calls Foo::ClassStaticFunc() in TranslationUnit1.cpp
}
请参阅内联说明符。由于ClassStaticFunc
完全在struct
定义中定义,因此它隐式是一个内联函数。允许在每个翻译单元中定义一次内联函数(而不是通常每个程序一次(。
如果这些定义不相同,则为未定义的行为。因此,通常只有一个(头(文件包含定义,然后由需要它的每个翻译单元共享。
它多次违反一个定义规则 (ODR(。 不需要诊断。 内联静态成员函数通常假定可能在多个源模块中定义(因为标头将被多次包含(,因此链接器将在任何地方只使用一个定义并忽略其余定义(因为遵守 ODR 意味着多个定义是相同的(。
但是,全局函数只应定义一次,链接器更有可能报告它们的多个定义,因为它通常指示错误。
相关文章:
- vscode g++链路故障:体系结构x86_64的未定义符号
- 在 Mac 上使用 CMAKE 将 FFTW 和 FFTWPP 链接到项目中时未定义的符号
- 在C++中使用内联方法时出现未定义的符号错误
- 引擎节点:未定义的符号:_ZTV6Config
- 为函数定义符号不明确的指针参数
- 未定义的引用,尽管存在符号,但 std::experimental::可选
- 体系结构x86_64的未定义符号:std:terminate(),typeinfo,运算符delete[],运算符new
- Windows 链接器是否使用 LoadLibrary 解析 DLL 中未定义的符号?
- C++ 中 dlsym 的未定义符号
- MacOS 上的 Xcode 11 项目不在一个函数中使用 sin 和 cos:未定义的符号"___sincosf_stret"
- 仅在 MacOS 上析构函数的未定义符号
- 重复符号 --- 定义和声明之间的差异
- 符号定义多次
- C++部分模板专用化和多符号定义错误
- 使用Visual Studio 2015时有多个符号定义
- CMake和Dylib:符号定义
- g++说引用是未定义的,即使' nm '列出了我的目标文件中的符号定义
- 为什么't my include保护防止递归包含和多个符号定义
- 多个符号定义,但我只定义我的符号一次
- 用c++科学和工程符号定义Flex实类型