c - 为什么链接存档时会出现 'multiple definition' 错误?

标签 c unit-testing linker cpputest

我正在使用 CppUTest 来测试 fornol.c 中定义的 C 代码源文件。该文件定义了主要生产 main()功能。

我还有一个AllTests.cpp文件也有 main()功能,但是main()应该仅在运行单元测试时使用。

AllTests.cpp被编译为 .o文件,而 fornol.c被编译为 libfornol.a存档。

然后 CppUTest 尝试将所有内容链接在一起,但我得到的是:

Linking fornol_tests
cc    -o fornol_tests objs/tests/AllTests.o objs/tests/FornolTests.o lib/libfornol.a ../../CppUTest/lib/libCppUTest.a ../../CppUTest/lib/libCppUTestExt.a -lstdc++ -lgcov
lib/libfornol.a(fornol.o): In function `main':
/home/dlindelof/Work/endor/nol/fornol/fornol.c:453: multiple definition of `main'
objs/tests/AllTests.o:/home/dlindelof/Work/endor/nol/fornol/tests/AllTests.cpp:4: first defined here
collect2: ld returned 1 exit status

看起来好像 main() fornol.c 中定义的函数并存在于文件中libfornol.amain() 冲突定义于 AllTests.cpp 。但我的理解是,仅当给定符号尚未被引用时才会搜索存档/库文件。因此,只要所有定义都在存档/库文件中,多次定义相同的符号应该不是问题。

我在这里做错了什么?

最佳答案

您需要从 AllTests.cpp 中删除 main() 并将其放入自己的源文件中。

当链接器在库中进行链接时,它无法拆分库中的目标文件;它必须将库中的每个目标文件作为一个单元进行链接或省略。 (我知道 LLVM 是不同的,但那是另一个话题了。)这就是为什么,如果您查看像 glibc 这样的库的源代码,每个函数都有自己的源文件。

因此,链接器需要从库 (libfornol.a) 中提取目标文件 (fornol.o) 来满足依赖关系,但该目标文件带有重复的符号 (main)。

将测试代码放入库中(我们在工作中经常这样做)是完全可以的,但将其保留在自己的源文件中(我们传统上使用 main.cc)。 (无论如何,这是一个更好的测试,因为测试代码不应该访问 static 声明的符号。)

关于c - 为什么链接存档时会出现 'multiple definition' 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9129087/

相关文章:

c - eventfd_write线程安全吗?

node.js - Mocha 的代码覆盖率

c# - 如何针对仅支持 SSL 的 Web Api Controller 对请求进行单元测试?

c++ - undefined reference gcc cxa

c printf(%*s) 解释

c++ - 如何在 DLL 中返回 vector ?

c - 对 pthread_create 的 undefined reference

javascript - 如何 stub new Worker()

c++ - GLEW 链接器错误 undefined reference to '_glew*'

assembly - MinGW 32 "undefined reference to ` 退出进程@ 4'"