提高测试 - “未定义引用”错误 [英] boost test - 'undefined reference' errors

查看:323
本文介绍了提高测试 - “未定义引用”错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个简单的文件:

runner.cpp:

 的#define BOOST_TEST_DYN_LINK
#定义BOOST_TEST_MODULE主
#包括LT&;升压/测试/ unit_test.hpp>

和test1.cpp:

 的#define BOOST_TEST_DYN_LINK
#IFDEF STAND_ALONE
#定义BOOST_TEST_MODULE主
#万一
#包括LT&;升压/测试/ unit_test.hpp>BOOST_AUTO_TEST_SUITE(美孚)BOOST_AUTO_TEST_CASE(TestSomething)
{
    BOOST_CHECK(真);
}BOOST_AUTO_TEST_SUITE_END()

要编译,我使用的是:

  $ G ++ -I / E / code / boost_1_52_0 -o亚军-lboost_unit_test_framework runner.cpp test1.cpp

我收到以下错误:

  C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ ccU0cDSz.o:runner.cpp :(文字+ 0x8c):多重定义'主'
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):首先这里定义
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):未定义的引用`init_unit_test_suite(INT,CHAR **)
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ ccU0cDSz.o:runner.cpp :(文字+ 0×52):未定义的参考`_imp___ZN5boost9unit_test9framework17master_test_suiteEv
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ ccU0cDSz.o:runner.cpp :(文字+ 0XB0):未定义的参考`_imp___ZN5boost9unit_test14unit_test_mainEPFbvEiPPc
C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerD2Ev[__ZN5boost9unit_test13test_observerD2Ev]+0xe):未定义的引用`_imp___ZTVN5boost9unit_test13test_observerE
C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerC2Ev[__ZN5boost9unit_test13test_observerC2Ev]+0xe):未定义的引用`_imp___ZTVN5boost9unit_test13test_observerE
C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test15unit_test_log_tC1Ev[__ZN5boost9unit_test15unit_test_log_tC1Ev]+0x22):未定义的引用`_imp___ZTVN5boost9unit_test15unit_test_log_tE
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ cciSdkmB.o:test1.cpp :(文字+均为0x88):未定义的参考`_imp___ZN5boost9unit_test15unit_test_log_t14set_checkpointENS0_13basic_cstringIKcEEjS4_
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ cciSdkmB.o:test1.cpp :(文字+ 0x136):未定义引用`_imp___ZN5boost10test_tools9tt_detail10check_implERKNS0_16$p$pdicate_resultERKNS_9unit_test12lazy_ostreamENS5_13basic_cstringIKcEEjNS1_10tool_levelENS1_10check_typeEjz'
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ cciSdkmB.o:test1.cpp :(文字+ 0x21d):未定义的参考`_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1ENS0_13basic_cstringIKcEE
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ cciSdkmB.o:test1.cpp :(文字+量0x284):未定义的参考`_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1EPNS0_9test_caseEm
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ cciSdkmB.o:test1.cpp :(文字+ 0x2a4):未定义的参考`_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1Ei
C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\cciSdkmB.o:test1.cpp:(.text$_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[__ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x1d):未定义的引用`_imp___ZN5boost9unit_test9ut_detail24normalize_test_case_nameENS0_13basic_cstringIKcEE
C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\cciSdkmB.o:test1.cpp:(.text$_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[__ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x5b):未定义的引用`_imp___ZN5boost9unit_test9test_caseC1ENS0_13basic_cstringIKcEERKNS0_9callback0INS0_9ut_detail6unusedEEE'
collect2.exe:错误:LD返回1退出状态

我使用MinGW的G ++ 4.7.2,用升压1.52.0。

我得到同样的错误时,只试图编译 test1.cpp - 除多个主要定义一

仔细端详了好一阵子的官方文档,但其对有关链接选项的详细信息很少。当我编译升压库,除了 unit_test_framework ,我也得到了 prg_exec_monitor test_exec_monitor ;也许我应该以某种方式链接这些?我试过很多的组合,但都造成了某种不确定的参考链接错误的。

升压产生库的完整列表 - 我把它们都在项目的根:

  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。图书馆需要指定的之后使用它们的对象和来源。

如上所述这里


  

接头的传统行为是搜索来自外部功能
  从左到右在命令行上指定的库。这意味着
  包含函数的定义库应任何信号源后出现
  文件或使用它的目标文件。这包括与指定的库
  短切-l选项,如图下面的命令:


  
  

$ GCC -Wall calc.c -lm -o计算(正确的顺序)


  
  

对于某些链接器相反的顺序(放置-lm选项文件之前
  它使用它)将导致一个错误,


  
  

$ CC -Wall -lm calc.c -o计算(不正确的顺序)结果
   main.o中:在函数'主':结果
   main.o中(的.text + 0xF的):未定义引用'开方'


  
  

由于存在含有calc.c后开方没有图书馆或目标文件。该
  该文件后,选项-lm应该出现'calc.c


2。库路径应当明确规定。

如果没有指定的lib路径,链接器可能会寻找在一系列库
默认文件夹,从而加载不同的库,然后打算。这是什么
在我的情况发生了 - 我想链接 boost_unit_test_framework ,但没有
因为我认为连接器看起来在当前文件夹指定的路径。
这是在运行时会发生什么,毕竟 - 如果 DLL 是在同一文件夹
exe文件,它会找到它。

我觉得有点怪怪的连接器将发现的lib,因为它是
名为 ibboost_unit_test_framework-mgw47-MT-1_52.dll 。当我试图链接
不存在lib目录,链接器虽然抱怨,所以我认为这不是一个
问题,的MinGW 的链接器会忽略这些后缀。

在一些更多的研究,我发现<一个href=\"http://www.mingw.org/wiki/HOWTO_Specify_the_Location_of_External_Libraries_for_use_with_MinGW\">this关于MinGW的库路径文章。
MinGW的搜索库中的文件夹可以在的输出中找到的gcc -print-搜索迪尔斯
文章还包含一些庆典魔法使该输出感:

 的gcc -print-搜索迪尔斯| SED'/ ^ LIB / B 1,D,:; [^ /] 1秒,/ [^ /] * / \\ \\ ./,/ ,;牛逼1; S,:[^ =] * =, :;; S,;; ,G'| TR \\; \\\\ 012 | grep的-v'^ * /

这将打印这些文件夹的一个很好的列表。 GCC 将的的,默认情况下,
看在库的当前目录。我看着在他们每个人,并发现
当时正在加载LIB - libboost_unit_test_framework.a ,静态库

这将带来光的另一个问题值得一提的:

3。静态与动态链接

我没有指定我是否要 boost_unit_test_framework 静态或动态链接。
在这种情况下, GCC prefers动态链接


  

由于这些优点GCC编译使用由共享库的程序
  默认在大多数系统上,如果他们都可用。每当一个静态库
  将用于与选项联'libName.a的'-lname编译器
  对于具有相同名称和。所以'替代共享库首先检查
  扩展。


所以是在Unix动态库的扩展 - 在Windows上,相当于是 DLL

那么,什么情况是, GCC 看了 libboost_unit_test_framework.dll
在所有它的默认文件夹,但无法找到它。然后找
libboost_unit_test_framework.a 和静态链接的。这导致
链接错误,因为源有的#define BOOST_TEST_DYN_LINK ,和
因此,期望有下的lib动态链接。

要执行静态或动态链接时, -Wl,-Bstatic 轮候册,-Bdynamic
链接选项开始发挥作用,可谓 href=\"http://stackoverflow.com/q/6578484/447661\">。

如果我告诉大家,我要动态链接的链接:

  $ G ++ -I / E / code / boost_1_52_0 runner.cpp test1.cpp -o亚军轮候册,Bdynamic -lboost_unit_test_framework

这将失败,因为链接器将无法找到 DLL

4.Summary

的问题是:


  1. 凡用他们的来源之前指定的库

  2. 未指定库路径

  3. 未指定连接的类型

  4. 库的名称不正确

最后,工作命令:

  $ G ++ -I / E / code / boost_1_52_0 -o亚军runner.cpp test1.cpp -L。轮候册,-Bdynamic -lboost_unit_test_framework-mgw47-MT-1_52

I have two simple files:

runner.cpp:

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>

and 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()

To compile, I'm using:

$ g++ -I/e/code/boost_1_52_0 -o runner -lboost_unit_test_framework runner.cpp test1.cpp

I get the following error:

C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.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~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text+0x52): undefined reference to `_imp___ZN5boost9unit_test9framework17master_test_suiteEv'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text+0xb0): undefined reference to `_imp___ZN5boost9unit_test14unit_test_mainEPFbvEiPPc'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerD2Ev[__ZN5boost9unit_test13test_observerD2Ev]+0xe): undefined reference to `_imp___ZTVN5boost9unit_test13test_observerE'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerC2Ev[__ZN5boost9unit_test13test_observerC2Ev]+0xe): undefined reference to `_imp___ZTVN5boost9unit_test13test_observerE'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.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~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x88): undefined reference to `_imp___ZN5boost9unit_test15unit_test_log_t14set_checkpointENS0_13basic_cstringIKcEEjS4_'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.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~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x21d): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1ENS0_13basic_cstringIKcEE'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x284): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1EPNS0_9test_caseEm'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x2a4): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1Ei'
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.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~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.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

I'm using g++ 4.7.2 on MinGW, with boost 1.52.0.

I get the same errors when only trying to compile test1.cpp - except the "multiple main definition" one.

I perused the official documentation for quite a while, but its scarce on details regarding linking options. When I compiled the boost libs, besides unit_test_framework, I also got prg_exec_monitor and test_exec_monitor; perhaps I should link these somehow ? I tried many combinations, but all resulted in some kind of undefined reference linker error.

Complete list of boost generated libraries - I have them all in the project root:

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

解决方案

With help from @llonesmiz, a number of issues were identified.

1. Libraries need to be specified after objects and sources which use them.

As described here:

The traditional behavior of linkers is to search for external functions from left to right in the libraries specified on the command line. This means that a library containing the definition of a function should appear after any source files or object files which use it. This includes libraries specified with the short-cut -l option, as shown in the following command:

$ gcc -Wall calc.c -lm -o calc (correct order)

With some linkers the opposite ordering (placing the -lm option before the file which uses it) would result in an error,

$ cc -Wall -lm calc.c -o calc (incorrect order)
main.o: In function 'main':
main.o(.text+0xf): undefined reference to 'sqrt'

because there is no library or object file containing sqrt after ‘calc.c’. The option -lm should appear after the file ‘calc.c’

2. Library paths should be explicitly specified.

If no lib paths are specified, the linker might look for the libs in a series of default folders, thus loading a different library then intended. This is what happened in my case - I wanted to link boost_unit_test_framework, but did not specify a path because I assumed the linker would look in the current folder. That's what happens at runtime, after all - if the dll is in the same folder with the exe, it will find it.

I found it a little bit strange the linker would find the lib, since it was named ibboost_unit_test_framework-mgw47-mt-1_52.dll. When I tried to link to a non-existing lib, the linker complained though, so I assumed this isn't an issue, and MinGW 's linker ignores those suffixes.

After some more research, I found this article about MinGW library paths. The folders MinGW searches for libs can be found in the output of gcc -print-search-dirs. The article also contains some bash magic to make sense of that output:

gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,;  ,g' | tr \; \\012 | grep -v '^ */'

This will print a nice list of those folders. gcc will not, by default, look in the current directory for libs. I looked in each of them, and found the lib that was being loaded - libboost_unit_test_framework.a, a static lib.

This brings into light another issue worth mentioning:

3. Static versus dynamic linking

I did not specify whether I want boost_unit_test_framework linked statically or dynamically. In this case, gcc prefers dynamic linking:

Because of these advantages gcc compiles programs to use shared libraries by default on most systems, if they are available. Whenever a static library ‘libNAME.a’ would be used for linking with the option -lNAME the compiler first checks for an alternative shared library with the same name and a ‘.so’ extension.

(so is the extension for dynamic libraries on Unix - on Windows, the equivalent is dll.)

So, what happened is that gcc looked for libboost_unit_test_framework.dll in all it's default folders, but couldn't find it. Then it looked for libboost_unit_test_framework.a, and statically linked that. This resulted in linking errors because the sources have #define BOOST_TEST_DYN_LINK, and therefore expect to have the lib dynamically linked.

To enforce static or dynamic linking, the -Wl,-Bstatic and -Wl,-Bdynamic linker options come into play, described here.

If I tell the linker that I want dynamic linking:

$ g++ -I/e/code/boost_1_52_0 runner.cpp test1.cpp -o runner -Wl,Bdynamic -lboost_unit_test_framework

This will fail, because the linker will not be able to find the dll.

4.Summary

The issues were:

  1. libraries where specified before the sources which used them
  2. the lib path wasn't specified
  3. the type of linking wasn't specified
  4. the name of the library was not correct

Final, working command:

$ 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

这篇关于提高测试 - “未定义引用”错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆