为什么在定义变量和链接库时"undefined reference"?

Why "undefined reference" when the variable is defined and the library is linked?

本文关键字:undefined reference 链接 定义 变量 为什么      更新时间:2023-10-16

我们有一些应用程序链接到我们自己的几个库。我最近添加了一个链接到这些库的新应用程序,该应用程序在Windows上成功编译。

但是,在 Linux 上,我看到对静态变量的"未定义引用"错误,这当然意味着未定义该变量。该错误发生在库中,但仅在链接到新应用程序时(现有应用程序仍可正常链接(。

如您所见,编译器说kAppVersion是未定义的。当它实际上是在 Version.cpp 中定义的,并且 common 是链接的(在 CMakeLists.txt 中指定(。我们认为这可能与target_link_libraries排序有关,但common移动到base之前(发生错误的位置(似乎没有效果。此外,在其他CMakeList中.txt(例如,为了协同作用(,排序似乎无关紧要,因为此应用程序已成功编译。这个类似的问题似乎暗示了排序很重要,但我在这方面没有任何成功:

问题:库已链接,但引用未定义

我唯一的想法是,在 synergyd.cpp 或 CDaemonApp 中可能有问题.cpp但我看不到任何在 Linux 上编译而不是 Windows 上的

明显东西。
Scanning dependencies of target synergyd
[ 90%] Building CXX object src/cmd/synergyd/CMakeFiles/synergyd.dir/synergyd.o
Linking CXX executable ../../../../../bin/debug/synergyd
../../../../../lib/debug/libarch.a(CArch.o): In function `~XExitApp':
/srv/buildbot/synergy/1.4-linux32/build/src/lib/arch/../synergy/XSynergy.h:114: undefined reference to `vtable for XExitApp'
../../../../../lib/debug/libarch.a(CArch.o): In function `CArchAppUtil::exitApp(int)':
/srv/buildbot/synergy/1.4-linux32/build/src/lib/arch/CArchAppUtil.h:31: undefined reference to `XExitApp::XExitApp(int)'
/srv/buildbot/synergy/1.4-linux32/build/src/lib/arch/CArchAppUtil.h:31: undefined reference to `typeinfo for XExitApp'
../../../../../lib/debug/libarch.a(CArchAppUtilUnix.o): In function `CArchAppUtilUnix::parseArg(int const&, char const* const*, int&)':
/srv/buildbot/synergy/1.4-linux32/build/src/lib/arch/CArchAppUtilUnix.cpp:32: undefined reference to `CApp::isArg(int, int, char const* const*, char const*, char const*, int)'
/srv/buildbot/synergy/1.4-linux32/build/src/lib/arch/CArchAppUtilUnix.cpp:37: undefined reference to `CApp::isArg(int, int, char const* const*, char const*, char const*, int)'
../../../../../lib/debug/libbase.a(CLog.o): In function `CLog::insert(ILogOutputter*, bool)':
/srv/buildbot/synergy/1.4-linux32/build/src/lib/base/CLog.cpp:213: undefined reference to `kAppVersion'
collect2: ld returned 1 exit status
make[2]: *** [../../bin/debug/synergyd] Error 1
make[1]: *** [src/cmd/synergyd/CMakeFiles/synergyd.dir/all] Error 2
make: *** [all] Error 2

完整的代码可以从我们的存储库中浏览。

简而言之,

真正的问题:archsynergy之间的循环库依赖关系。此外,base实际上没有链接到common库(在 CMakeList 中.txt base(。

有趣的是,这是由库的 CMakeLists.txt 文件中的配置问题引起的。这与CMakeLists无关.txt对于我添加的新synergyd应用程序。

问题是我没有将库相互链接,其中新调用被添加到其他库中的类。但是,现在似乎存在循环链接的问题。

例如,我本可以添加...

if (UNIX)
    target_link_libraries(arch synergy)
endif()

。到 CMakeLists.txt在arch库中,就像arch现在在synergy库中调用某些内容一样。但这是无效的,因为synergy已经在arch中调用了某些东西.

显然,这在Windows上无关紧要。

我不太确定是什么原因导致这种情况开始发生,因为它都是以前编译良好的旧代码,并且在其他应用程序中仍然如此。我怀疑很可能与最近从 CArch 中删除样板有关,而不是 CDaemonApp 正在做的事情(甚至可能是两者的结合(。

更新

以防万一有人关心 ;-( - 我认为这与 archsynergy 之间糟糕的循环库依赖关系有关,再加上CDaemonApp.cpp不包括CApp.h的事实 - 这意味着它包含在其他点,导致奇怪的未定义引用错误。

为了正确解决这个问题,我删除了循环依赖,这似乎是问题的核心。

更新 2

代码现在完全编译,万岁!

我仍然看到最后一个错误(这个问题的主题(:

[ 90%] Building CXX object src/cmd/synergyd/CMakeFiles/synergyd.dir/synergyd.o
Linking CXX executable ../../../../../bin/debug/synergyd
../../../../../lib/debug/libbase.a(CLog.o): In function `CLog::insert(ILogOutputter*, bool)':
/home/nick/Projects/synergy/branches/1.4/src/lib/base/CLog.cpp:213: undefined reference to `kAppVersion'
collect2: ld returned 1 exit status
make[2]: *** [../../bin/debug/synergyd] Error 1
make[1]: *** [src/cmd/synergyd/CMakeFiles/synergyd.dir/all] Error 2
make: *** [all] Error 2

这仅仅是由于base库未链接到common库造成的。将以下代码添加到 CMakeLists.txt 文件以修复此问题:

if (UNIX)
    target_link_libraries(base common)
endif()

仍然不确定为什么开始发生这种情况,只是很高兴它已修复。

更新 3

这是提交:r1354

首先,链接的顺序确实很重要,至少对于 g++ 来说是这样。如果A使用B中的符号,那么B应该在Ag++ ... -lA -lB之后提及

我也看到了一个undefined reference to vtable for XExitApp.此错误表示您在XExitApp中有一个未定义的虚拟函数。如果您不想定义该函数,请通过添加= 0使其成为纯虚拟

函数

我唯一注意到的是你缺少"../../lib/synergy"在/synergyd/CMakeLists.txtset(inc...部分中。这是否与问题有关,我只能猜测。

您收到的所有链接错误似乎是由于链接器找不到它正在寻找的符号。这样做的常见原因是相关的 .o 文件不存在、未包含在构建中或编译不正确。

我将首先清理,更改 CMakeList.txt 文件以尽可能匹配已知的工作版本,并在打开所有编译器/警告的情况下重建所有内容。如果这不起作用(相同的错误或不同的错误(,我会更仔细地查看哪些有效,哪些无效。你说Windows版本有效,但Linux版本不行。两者之间有什么区别,其中哪些可以解释这个问题。与一个正确构建的类似项目类似:两个项目之间有什么区别。