io uso Visual Studio 2012. La mia configurazione è simile a questo:std :: basic_ostringstream esportato da Boost quadro unit test risultati dll in un "simbolo già definito" -Errore
- link some.lib contro some.exe
- link some.lib contro some_test.exe
io uso BOOST_TEST_DYN_LINK quando si costruisce some_test.exe. I risultati sono gli stessi utilizzando BOOST_ALL_DYN_LINK per some.lib e test.exe.
Ho creato some_test.exe, some.exe e some.lib con/MD (Multi-Threaded DLL). Ho creato le librerie boost con runtime-link = shared. Tutti sono costruiti e collegati da VC11 (Visual Studio 2012).
Il problema è, in some.lib, vorrei utilizzare la variabile locale
std::ostringstream someStream;
Il some.exe collegamenti sottili. Ma quando collega la some_test.exe, che collega in modo dinamico al quadro unit test spinta (1.59) che mi dà 3 errori (LNK2005):
errori
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)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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 " ([email protected]?$basic_ostrin[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]) 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)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@QEAAXXZ) already defined in some.lib(some.obj)
some_test.exe : fatal error LNK1169: one or more multiply defined symbols found
Lo stesso accade quando si utilizza 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)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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 " ([email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]) 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)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@QEAAXXZ) already defined in some.lib(some.obj)
some_test.exe : fatal error LNK1169: one or more multiply defined symbols found
Strane dipendenze
ho corse Dependency Walker sul file boost_unit_test_framework-vc110-mt-1_59.dll
012.[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@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)
o decorati:
[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@Z
[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@Z
[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@Z
Per confronto, ho scaricato boost_unit_test_framework-vc110-mt-1_61.dll da
https://sourceforge.net/projects/boost/files/boost-binaries/
e che dll esporta anche quelle contrastanti simboli ostringstream
[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@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)
Quindi questo sembra un comportamento normale per il framework di test. Anche se, per me non sembra una buona idea esportare quei simboli in una DLL.
Ho anche fatto un dumpbin /symbols some.lib
Non ci trovo i simboli contrastanti:
2AFC 00000000 SECT1183 notype() External | [email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected] (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 | [email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]
43D4 00000000 SECT16FB notype Static | [email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]
2AFA 00000000 SECT6AF notype() External | [email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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 | [email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@Z
43B9 00000000 SECT16F2 notype Static | [email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@Z
43BC 00000000 SECT16F3 notype Static | [email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@Z
43BF 00000000 SECT16F4 notype Static | [email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@Z
43C2 00000000 SECT16F5 notype Static | [email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@Z
2B0E 00000000 SECTA3C notype() External | [email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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 | [email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@QEAAXXZ
4449 00000000 SECT1722 notype Static | [email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@QEAAXXZ
Per quanto ho capito, i simboli (corrispondenti esatto) sono contrassegnati "esterno" in some.lib. Quindi non sono collegati staticamente dal runtime in some.lib, ma in modo dinamico.
Conosciuto Soluzioni alternative
posso aggirare il problema sia utilizzando bei std::stringstream
invece di std::ostringstream
nella fonte di some.lib.Penso che potrei vivere con quello, ma sarebbe difficile capire per qualsiasi manutentore, perché non si sarebbe permesso di usare ostringstream.
In alternativa, potrei usare la Linker-Flag /FORCE:MULTIPLE
per some_test.exe e effettuare il downgrade dell'errore LNK2005 a un LNK4006 di avviso. Ma non mi piacciono i perma-warnings, specialmente se sono solo errori mascherati.
le domande
Qual è il modo giusto di usare il boost_unit_test_framework e non ottenere quei errori del linker?
Esporta intenzionalmente l'esportazione std::basic_ostringstream
o devo inviare una segnalazione di errore?
Sto facendo le domande sbagliate?
Varie
Il comportamento di MSVC sembra essere cambiato nella versione 2010. Prima, non ci sono errori. https://social.msdn.microsoft.com/Forums/vstudio/en-US/191de00a-53c9-4bd9-9cb6-e844eb224ca2/lnk2005-when-using-stdostringstream?forum=vclanguage
Dopo 8 giorni senza risposta o commento su SO, ho aperto una discussione sulla mailing-list boost-user. Se viene trovata una risposta, la condividerò tra SO e la mailing list, ovviamente. http://lists.boost.org/boost-users/2016/06/86332.php (come del 2017/08/17 c'è ancora nessuna soluzione data nella mailing list o)
Ora, 1 anno dopo, ho aggiornato a Visual Studio 2015 e ottenere lo stesso comportamento.
Giusto per essere sicuri, ha definito simbolo "BOOST_ALL_DYN_LINK"? – zahir
Avevo BOOST_TEST_DYN_LINK definito per some_test.exe, ma anche ricostruito e linke con BOOST_ALL_DYN_LINK impostato sia per alcuni.lib che some_test.exe. I 3 messaggi di errore rimangono gli stessi. – Sascha
Hai provato con VS 2015? Se il problema si presentava in una versione del compilatore, potrebbe essere scomparso in un'altra. – eh9