Ján*_*tal 5 c++ linker linker-errors multiple-definition-error
我遇到过这样的情况:librdkafka和Pulsar C++ 客户端的链接顺序不同确实很重要,因为它们都包含各自的 LZ4 压缩版本。由于 LZ4 函数的多个定义(librdkafka 和 Pulsar 的这些函数的名称相同),链接失败。我检查了静态库,但我找不到任何可疑的东西,为什么它按一个顺序工作而按另一个顺序却不工作。因为很难为这些大库提供最小的工作示例,所以我尝试重现相同的情况,并且我能够做到这一点。我创建了一个小项目,其中链接顺序很重要。
libA.hpp:
#pragma once
void NotClashingFunctionA();
void ClashingFunction();
Run Code Online (Sandbox Code Playgroud)
libA.cpp:
#include "libB.hpp"
#include <iostream>
void NotClashingFunctionA() {
std::cout << "Not clashing function A\n";
}
void ClashingFunction() {
std::cout << "Clashing function A\n";
}
Run Code Online (Sandbox Code Playgroud)
libB.hpp:
#pragma once
void NotClashingFunctionB();
Run Code Online (Sandbox Code Playgroud)
libB.cpp:
#include "libB.hpp"
#include <iostream>
void NotClashingFunctionB() {
std::cout << "Not clashing function B\n";
}
Run Code Online (Sandbox Code Playgroud)
libBSub.hpp:
#pragma once
void ClashingFunction();
Run Code Online (Sandbox Code Playgroud)
libBSub.cpp:
#include "libBSub.hpp"
#include <iostream>
void ClashingFunction() {
std::cout << "Clashing function B\n";
}
Run Code Online (Sandbox Code Playgroud)
主要.cpp:
#include "libA.hpp"
#include "libB.hpp"
#include "libBSub.hpp"
int main() {
NotClashingFunctionA();
NotClashingFunctionB();
ClashingFunction();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
CMakeLists.txt:
project(clashing)
add_library(A STATIC libA.cpp)
add_library(B STATIC libB.cpp libBSub.cpp)
add_executable(working main.cpp)
target_link_libraries(working A B)
add_executable(failing main.cpp)
target_link_libraries(failing B A)
Run Code Online (Sandbox Code Playgroud)
从日志中我可以清楚地看到working链接正常:
clang++ -g -rdynamic CMakeFiles/working.dir/main.cpp.o -o working libA.a libB.a
make[3]: Leaving directory 'build'
[100%] Built target working
Run Code Online (Sandbox Code Playgroud)
但failing无法链接:
clang++ -g -rdynamic CMakeFiles/failing.dir/main.cpp.o -o failing libB.a libA.a
ld: libA.a(libA.cpp.o): in function `ClashingFunction()':
libA.cpp:9: multiple definition of `ClashingFunction()'; libB.a(libBSub.cpp.o):libBSub.cpp:5: first defined here
clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)
我删除了常见的前缀以使日志更具可读性。
正如您所看到的,两者之间的唯一区别是链接顺序A和B。我不知道为什么它按A B顺序运行,而不是B A按顺序运行。
如果你不能详细解释它,也非常感谢帮助关键字,因为我完全不知道为什么会发生。
举一个具体的例子:
main.o定义main()、fn()、 以及引用a()和b()。libA.a包含a.o其中定义a()libB.a包含b.owhich 定义b(),也包含a1.owhich 定义a()和fn()。现在,如果使用 链接gcc main.o -lA -lB,则链接会成功(a.ofromlibA.a和b.ofromlibB.a会被选入链接,不会出现符号冲突。值得注意的是,a1.ofromlibB.a不会被选入链接)。
但如果用 链接gcc main.o -lB -lA,则将fn()被多重定义(因为 和a1.ofromb.o都会libB.a被选入链接,但fn()in的定义将与ina1.o的定义冲突)。fn()main.o