由 Boost 单元测试框架 dll 导出的 std::basic_ostringstream 会导致"already defined symbol"错误
std::basic_ostringstream exported by Boost unit test framework dll results in an "already defined symbol"-error
我使用Visual Studio2012。我的设置就是这样:
- some.lib链接到某个exe
- some.lib链接some_test.exe
我在构建some_test.exe时使用boost_test_dyn_link。使用BOOST_ALL_DYN_LINK用于some.lib和test.exe。
,结果是相同的。我已经构建了some_test.exe,some.exe和some.lib使用/md(多线程dll)。我已经使用Runtime-Link =共享构建了Boost Libs。所有这些都是由VC11构建和链接的(Visual Studio 2012)。
问题是,在某个lib中,我想使用local variable
std::ostringstream someStream;
some.exe链接正常。但是,当链接some_test.exe时,它动态地链接到Boost单元测试框架(1.59),它给了我3个错误(LNK2005):
错误
boost_unit_test_framework-vc110-mt-1_59.lib(boost_unit_test_framework-vc110-mt-1_59.dll) : error LNK2005: "public: __cdecl std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >(int)" (??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@H@Z) already defined in some.lib(some.obj)
boost_unit_test_framework-vc110-mt-1_59.lib(boost_unit_test_framework-vc110-mt-1_59.dll) : error LNK2005: "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::str(void)const " (?str@?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ) already defined in some.lib(some.obj)
boost_unit_test_framework-vc110-mt-1_59.lib(boost_unit_test_framework-vc110-mt-1_59.dll) : error LNK2005: "public: void __cdecl std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::`vbase destructor'(void)" (??_D?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAXXZ) already defined in some.lib(some.obj)
some_test.exe : fatal error LNK1169: one or more multiply defined symbols found
使用MSVC14(Visual Studio 2015)
时也会发生同样的情况boost_unit_test_framework-vc140-mt-1_59.lib(boost_unit_test_framework-vc140-mt-1_59.dll) : error LNK2005: "public: __cdecl std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char>>::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >(int)" (??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@H@Z) already defined in some.lib(some.obj)
boost_unit_test_framework-vc140-mt-1_59.lib(boost_unit_test_framework-vc140-mt-1_59.dll) : error LNK2005: "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::str(void)const " (?str@?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ) already defined in some.lib(some.obj)
boost_unit_test_framework-vc140-mt-1_59.lib(boost_unit_test_framework-vc140-mt-1_59.dll) : error LNK2005: "public: void __cdecl std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::`vbase destructor'(void)" (??_D?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAXXZ) already defined in some.lib(some.obj)
some_test.exe : fatal error LNK1169: one or more multiply defined symbols found
奇怪的依赖项
i在文件boost_unit_test_framework-vc110-mt-1_59.dll
上运行了依赖关系沃克??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@$$QEAV01@@Z
std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,int)
std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >(int)
或装饰:
??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@$$QEAV01@@Z
??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@1@H@Z
??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@H@Z
为了进行比较,我从
中下载了boost_unit_test_framework-vc110-mt-1_61.dllhttps://sourceforge.net/projects/boost/files/boost-binaries/
dll还导出那些冲突的oststream符号
??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@$$QEAV01@@Z
std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,int)
std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >(int)
因此,对于测试框架来说,这似乎是正常的行为。但是,对我来说,将这些符号导出到DLL似乎不是一个好主意。
我也做了dumpbin /symbols some.lib
在那里我找到了矛盾的符号:
2AFC 00000000 SECT1183 notype () External | ?str@?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ (public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::str(void)const )
43D1 00000000 SECT16FA notype Static | $unwind$?str@?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ
43D4 00000000 SECT16FB notype Static | $pdata$?str@?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ
2AFA 00000000 SECT6AF notype () External | ??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@H@Z (public: __cdecl std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >(int))
43B6 00000000 SECT16F1 notype Static | $unwind$??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@H@Z
43B9 00000000 SECT16F2 notype Static | $pdata$??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@H@Z
43BC 00000000 SECT16F3 notype Static | $cppxdata$??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@H@Z
43BF 00000000 SECT16F4 notype Static | $stateUnwindMap$??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@H@Z
43C2 00000000 SECT16F5 notype Static | $ip2state$??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@H@Z
2B0E 00000000 SECTA3C notype () External | ??_D?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAXXZ (public: void __cdecl std::basic_ostringstream<char,struct std::char_traits<char>,class std::allocator<char> >::`vbase destructor'(void))
4446 00000000 SECT1721 notype Static | $unwind$??_D?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAXXZ
4449 00000000 SECT1722 notype Static | $pdata$??_D?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAXXZ
据我了解,(确切的匹配)符号在某些lib中标记为"外部"。因此,它们不是从运行时静态链接到某个lib,而是动态的。
已知的解决方法
我可以使用std::stringstream
而不是std::ostringstream
解决问题。我认为我可以忍受这一点,但是对于任何维护者来说都是很难理解的,为什么不允许使用Oststream。
另外,我可以将Linker-FLAG /FORCE:MULTIPLE
用于Some_test.exe,然后将错误lnk2005降级到警告LNK4006。但是我不喜欢Perma-warnings,特别是如果它们只是掩盖错误。
问题
使用BOOST_UNIT_TEST_FRAMEWORK而没有获取这些链接器错误的正确方法是什么?
Boost是否有意导出std::basic_ostringstream
,还是我应该提交错误报告?
我问错误的问题吗?
MISC
MSVC的行为似乎在2010年版本中发生了变化。https://social.msdn.microsoft.com/forums/vstudio/en-us/191de00a-53c9-4bd9-4bd9-9cb6-e8444eb224ca2/lnk2005--
8天没有答案或评论后,我在Boost用户邮件列表上打开了一个线程。如果找到答案,我当然会在SO和邮件列表之间分享。http://lists.boost.org/boost-users/2016/06/86332.php(截至2017年8月17日,邮件列表中仍然没有提供解决方案)
现在,一年后,我升级到Visual Studio 2015并获得了相同的行为。
我敢打赌你在两个不同的c runtimes中拉动。一个通过Boost,另一个通过您的项目。请检查您的项目some_test.exe->配置属性 -> c/c ->代码生成 ->运行时库,然后尝试多线程dll。
通过搜索您的问题,我发现了以下建议,如果他们可以帮助您
使用BOOST_ALL_NO_LIB
添加到依赖项目的宏,并在主项目中添加到链接器输入必要的库中。添加/强制:链接命令行选项的多个。
来自MSDN:"使用/强制:多个链接为符号找到多个定义的输出文件。
"尝试以下操作:
选项
--build-type=complete
导致Boost Build构建全部 库的支持变体。使用/MTd
进行调试。
您也可以咨询此页面
我也有类似的问题,因为尝试了许多方法,以在我的项目中包括提升单元测试,并且具有重复的包含在内的文件,并且还重复了我的unit_test_main的定义。
- 理解boost::asio-async_read在无需读取内容时的行为
- boost::进程间消息队列引发错误
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- cmake如何在fedora工作站中找到boost静态库包
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- Boost Graph Library,修复节点大小
- 什么是"#include <boost/functional/hash.hpp> "?
- 基于boost的程序的静态链接——zlib问题
- C++:如何在CLion IDE中安装Boost
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 如何在boost beast http请求中设置http头
- Boost Spirit,获取迭代器内部语义动作
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- boost::asio如何生成多个协同程序,然后加入它们
- 当我尝试使用 sstream 和分面将 Boost Time_duration转换为字符串时,我没有得到所需的格式
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 使用Boost Interprocess创建托管共享内存需要很长时间
- 由 Boost 单元测试框架 dll 导出的 std::basic_ostringstream 会导致"already defined symbol"错误
- BOOST ASIO:为什么我不在Windows中得到"bind: Address already in use"(但在Linux中得到它)?