升压测试 - 'undefined reference'误差
boost test - 'undefined reference' errors
我有两个简单的文件:
runner.cpp:
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>
和test1.cpp:
#define BOOST_TEST_DYN_LINK
#ifdef STAND_ALONE
# define BOOST_TEST_MODULE Main
#endif
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE( Foo)
BOOST_AUTO_TEST_CASE( TestSomething )
{
BOOST_CHECK( true );
}
BOOST_AUTO_TEST_SUITE_END()
为了编译,我使用:
$ g++ -I/e/code/boost_1_52_0 -o runner -lboost_unit_test_framework runner.cpp test1.cpp
我得到以下错误:
C:DOCUME~1ADMINI~1LOCALS~1TempccU0cDSz.o:runner.cpp:(.text+0x8c): multiple definition of `main'
c:/pdev/mingw/bin/../lib/gcc/i686-pc-mingw32/4.7.2/../../../libboost_unit_test_framework.a(unit_test_main.o):unit_test_main.cpp:(.text.startup+0x0): first defined here
c:/pdev/mingw/bin/../lib/gcc/i686-pc-mingw32/4.7.2/../../../libboost_unit_test_framework.a(unit_test_main.o):unit_test_main.cpp:(.text.startup+0x14): undefined reference to `init_unit_test_suite(int, char**)'
C:DOCUME~1ADMINI~1LOCALS~1TempccU0cDSz.o:runner.cpp:(.text+0x52): undefined reference to `_imp___ZN5boost9unit_test9framework17master_test_suiteEv'
C:DOCUME~1ADMINI~1LOCALS~1TempccU0cDSz.o:runner.cpp:(.text+0xb0): undefined reference to `_imp___ZN5boost9unit_test14unit_test_mainEPFbvEiPPc'
C:DOCUME~1ADMINI~1LOCALS~1TempccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerD2Ev[__ZN5boost9unit_test13test_observerD2Ev]+0xe): undefined reference to `_imp___ZTVN5boost9unit_test13test_observerE'
C:DOCUME~1ADMINI~1LOCALS~1TempccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerC2Ev[__ZN5boost9unit_test13test_observerC2Ev]+0xe): undefined reference to `_imp___ZTVN5boost9unit_test13test_observerE'
C:DOCUME~1ADMINI~1LOCALS~1TempccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test15unit_test_log_tC1Ev[__ZN5boost9unit_test15unit_test_log_tC1Ev]+0x22): undefined reference to `_imp___ZTVN5boost9unit_test15unit_test_log_tE'
C:DOCUME~1ADMINI~1LOCALS~1TempcciSdkmB.o:test1.cpp:(.text+0x88): undefined reference to `_imp___ZN5boost9unit_test15unit_test_log_t14set_checkpointENS0_13basic_cstringIKcEEjS4_'
C:DOCUME~1ADMINI~1LOCALS~1TempcciSdkmB.o:test1.cpp:(.text+0x136): undefined reference to `_imp___ZN5boost10test_tools9tt_detail10check_implERKNS0_16predicate_resultERKNS_9unit_test12lazy_ostreamENS5_13basic_cstringIKcEEjNS1_10tool_levelENS1_10check_typeEjz'
C:DOCUME~1ADMINI~1LOCALS~1TempcciSdkmB.o:test1.cpp:(.text+0x21d): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1ENS0_13basic_cstringIKcEE'
C:DOCUME~1ADMINI~1LOCALS~1TempcciSdkmB.o:test1.cpp:(.text+0x284): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1EPNS0_9test_caseEm'
C:DOCUME~1ADMINI~1LOCALS~1TempcciSdkmB.o:test1.cpp:(.text+0x2a4): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1Ei'
C:DOCUME~1ADMINI~1LOCALS~1TempcciSdkmB.o:test1.cpp:(.text$_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[__ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x1d): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24normalize_test_case_nameENS0_13basic_cstringIKcEE'
C:DOCUME~1ADMINI~1LOCALS~1TempcciSdkmB.o:test1.cpp:(.text$_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[__ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x5b): undefined reference to `_imp___ZN5boost9unit_test9test_caseC1ENS0_13basic_cstringIKcEERKNS0_9callback0INS0_9ut_detail6unusedEEE'
collect2.exe: error: ld returned 1 exit status
我在MinGW上使用g++4.7.2,提升1.52.0。
当我只试图编译test1.cpp
时,我会遇到同样的错误——除了"多主定义"错误。
我仔细阅读了官方文档很长一段时间,但很少有关于链接选项的细节。当我编译boost库时,除了unit_test_framework
,我还得到了prg_exec_monitor
和test_exec_monitor
;也许我应该把这些联系起来?我尝试了许多组合,但都导致了某种未定义的引用链接器错误。
boost生成库的完整列表-我在项目根目录中有它们:
libboost_prg_exec_monitor-mgw47-mt-1_52.a
libboost_prg_exec_monitor-mgw47-mt-1_52.dll
libboost_prg_exec_monitor-mgw47-mt-1_52.dll.a
libboost_prg_exec_monitor-mgw47-mt-d-1_52.a
libboost_prg_exec_monitor-mgw47-mt-d-1_52.dll
libboost_prg_exec_monitor-mgw47-mt-d-1_52.dll.a
libboost_test_exec_monitor-mgw47-mt-1_52.a
libboost_test_exec_monitor-mgw47-mt-d-1_52.a
libboost_unit_test_framework-mgw47-mt-1_52.a
libboost_unit_test_framework-mgw47-mt-1_52.dll
libboost_unit_test_framework-mgw47-mt-1_52.dll.a
libboost_unit_test_framework-mgw47-mt-d-1_52.a
libboost_unit_test_framework-mgw47-mt-d-1_52.dll
libboost_unit_test_framework-mgw47-mt-d-1_52.dll.a
在@llonesmiz的帮助下,发现了许多问题。
1.库需要在对象和使用它们的源之后指定
如上所述:
链接器的传统行为是从在命令行上指定的库中从左到右。这意味着包含函数定义的库应出现在任何源之后使用它的文件或对象文件。这包括使用shortcut-l选项,如以下命令所示:
$ gcc -Wall calc.c -lm -o calc (correct order)
对于某些链接器,顺序相反(将-lm选项放在文件之前使用它的)会导致错误,
$ cc -Wall -lm calc.c -o calc (incorrect order)
main.o: In function 'main':
main.o(.text+0xf): undefined reference to 'sqrt'
因为在"calc.c"之后没有包含sqrt的库或对象文件选项-lm应出现在文件"calc.c"之后
2.应显式指定库路径
如果没有指定库路径,链接器可能会在一个系列中查找库默认文件夹,从而加载不同的库。这就是发生在我的情况下-我想链接boost_unit_test_framework
,但没有指定一个路径,因为我认为链接器将在当前文件夹中查找。毕竟,如果dll
在同一个文件夹中,那么运行时就会发生这种情况有了exe
,它就会找到它
我发现链接器会找到lib有点奇怪,因为它是命名为CCD_ 12。当我尝试链接到一个不存在的lib,链接器抱怨道,所以我认为这不是问题,并且MinGW
的链接器忽略这些后缀。
经过更多的研究,我发现了这篇关于MinGW库路径的文章。MinGW搜索库的文件夹可以在gcc -print-search-dirs
的输出中找到。这篇文章还包含了一些bash
的魔力来理解这个输出:
gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/../,/,;t 1;s,:[^=]*=,:;,;s,;,; ,g' | tr ; \012 | grep -v '^ */'
这将打印这些文件夹的漂亮列表。默认情况下,gcc
将而不是,在当前目录中查找libs。我查看了每一个,发现正在加载的lib-libboost_unit_test_framework.a
,一个静态lib。
这就引出了另一个值得一提的问题:
3.静态与动态链接
我没有指定是静态链接还是动态链接boost_unit_test_framework
。在这种情况下,gcc
更喜欢动态链接:
由于这些优势,gcc编译程序以使用共享库默认情况下,如果大多数系统可用。无论何时静态库"libNAME.a"将用于链接编译器的-lNAME选项首先检查具有相同名称和".so"的备用共享库扩大
(so
是Unix上动态库的扩展-在Windows上,相当于dll
。)
所以,发生的事情是gcc
寻找libboost_unit_test_framework.dll
在所有默认文件夹中,但找不到它。然后它查找libboost_unit_test_framework.a
,并将其静态链接。这导致由于源具有#define BOOST_TEST_DYN_LINK
而导致的链接错误,以及因此,期望lib动态链接。
为了强制执行静态或动态链接,-Wl,-Bstatic
和-Wl,-Bdynamic
链接器选项开始发挥作用,如下所述。
如果我告诉链接器我想要动态链接:
$ g++ -I/e/code/boost_1_52_0 runner.cpp test1.cpp -o runner -Wl,Bdynamic -lboost_unit_test_framework
这将失败,因为链接器将无法找到dll
。
4.摘要
问题是:
- 库,在使用它们的源之前指定
- 未指定lib路径
- 未指定链接的类型
- 库的名称不正确
最终工作命令:
$ g++ -I/e/code/boost_1_52_0 -o runner runner.cpp test1.cpp -L. -Wl,-Bdynamic -lboost_unit_test_framework-mgw47-mt-1_52
- 为什么在浮点中从大到小会引入更多的误差
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- Visual Studio Code "undefined reference to `WinMain@16'"
- 使用 MATLAB 编码器生成C++代码:编译错误"undefined reference to `rgb2gray_tbb_real64'"
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 为什么创建友元类的实例会导致"undefined reference to"错误?
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- Tensorflow c++ api undefined reference to 'tflite::D efaultErrorReporter()'
- 不断"Attempting to reference a deleted function"
- std::iterator::reference 必须是引用吗?
- C++/SDL "initial value of reference to a non-const must be an lvalue"
- 为什么在使用 SDL2 时仍然收到'undefined reference'链接器错误?
- OpenCV undefined reference to 'cv::imread(cv::String const&, int)'
- Libcurl c++ "undefined reference to" (Windows/MinGW/g++)
- C++返回类型 T(&)[] 与使用 reference = T(&)[] 作为返回类型
- 基于相邻元素 c++ 的分段误差范围的循环
- const auto & 和 auto & if reference 对象之间的区别是 const
- 尝试使用 extern "C" 调用 C 中的C++方法,得到"undefined reference to"对象的链接器错误
- 以前的'namespace reference { }'声明
- 升压测试 - 'undefined reference'误差