为什么不在这个静态库中创建多个已定义的符号?

Why doesn't this create multiple defined symbols in this static library?

在静态库项目中,我有一个 header 文件,其中包含已声明但未实现的函数。

我有一个实现这些功能的 .cpp 文件。

然后,为了更好地理解链接器错误,我复制了 cpp 文件,所以我有一个完全相同的副本,它也被编译了。因此,这两个文件对 header.

中的每个符号都有双重实现

它编译,当在另一个项目中使用时,它链接。

这里是静态库的最小示例:

api.hpp:

void printWhatever();

errortest.cpp 和 duplicate.cpp 相同:

#include "api.hpp"
#include <iostream>
void printWhatever(){
  std::cout << "hi " << "\n";
}

我用这两个源文件将其编译为静态库。我看到编译器为这两个文件生成报告。

现在我在一个不同的项目的可执行文件中使用这个编译库: main.cpp:

#include <api.hpp>
int main(int argc, const char * argv[]) {
  printWhatever();

  return 0;
}

它运行并打印 "hi"。

为什么函数没有多重定义?

以下示例会产生所需的链接错误:

main.cpp

int demo();
int main() { return demo(); }

file1.cpp

int demo() { return 1; }

file2.cpp

int demo() { return 2; }

编译

g++ main.cpp file1.cpp file2.cpp

/tmp/ccdzSL9x.o: In function demo()': file2.cpp:(.text+0x0): multiple definition ofdemo()' /tmp/cc7Hzvrb.o:file1.cpp:(.text+0x0): first defined here collect2: error: ld returned 1 exit status

How to create a multiple defined symbols linking error

非常小的 shell 程序,用于生成违反一个定义规则的非常小的格式错误的 C++ 程序:

echo 'int main(){}' | tee a.cpp > b.cpp
g++ a.cpp b.cpp

应该很容易了解正在发生的事情。有两个源文件都定义了一个非内联函数 int main(),因此违反了 odr.

添加到这个问题的关键事实是,具有重复符号的两个模块被链接到一个静态库.

静态库与共享库的工作方式截然不同。链接时,链接器在静态库中搜索引用的符号。定义引用符号的第一个模块被链接以生成最终的可执行文件。另一个模块定义相同符号的事实无关紧要。如果具有重复符号的其他模块未定义可执行文件所需的任何其他符号,则它不会链接到可执行文件中。

如果您想查看静态库的重复错误:

从您的 main() 呼叫 foo()bar()

在静态库的第一个模块中定义foo()baz()

在静态库的第二个模块中定义bar()baz()

因为两个模块都包含从 main() 引用的符号,它们被迫与可执行文件链接,导致由于 baz().

而导致重复符号错误