Używam Visual Studio 2012. Moja konfiguracja wygląda następująco:std :: basic_ostringstream eksportowane przez jednostki doładowania ramowych Test dll wyników w "już zdefiniowanym symbolem" -error
- linki some.lib przeciwko some.exe
- linki some.lib przeciwko some_test.exe
używam BOOST_TEST_DYN_LINK przy budowie some_test.exe. Wyniki są takie same za pomocą BOOST_ALL_DYN_LINK dla some.lib i test.exe.
Zbudowałem plik some_test.exe, some.exe i some.lib z/MD (Multi-Threaded DLL). Zbudowałem biblioteki boost z runtime-link = shared. Wszystkie są zbudowane i połączone przez VC11 (Visual Studio 2012).
Problem jest w some.lib, chciałbym użyć zmiennej lokalnej
std::ostringstream someStream;
some.exe łączy grzywny. Ale gdy powiązanie some_test.exe, który dynamicznie linki do ram badanej jednostki doładowania (1,59) daje mi 3 błędy (LNK2005):
błędy
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][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
To samo dzieje się w przypadku korzystania 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
Dziwne Zależności
Pobiegłem Dependency Walker na pliku boost_unit_test_framework-vc110-mT-1_59.dll
[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)
lub zdobione:
[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected][email protected]@Z
[email protected][email protected]@[email protected]@V?$allocator[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
Dla porównania Pobrałem boost_unit_test_framework-vc110-MT-1_61.dll z
https://sourceforge.net/projects/boost/files/boost-binaries/
i że dll eksportuje także te sprzeczne symbole 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)
To wydaje się normalne zachowanie dla ramy testu. Chociaż dla mnie nie wydaje się dobrym pomysłem eksportowanie tych symboli do biblioteki dll.
Ja też zrobiłem dumpbin /symbols some.lib
Tam znaleźć sprzeczne symbole:
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
O ile mi zrozumieć, że (dokładne dopasowania) symbole są oznaczone jako „zewnętrzny” w some.lib. Nie są więc statycznie połączone ze środowiskiem wykonawczym w pliku some.lib, ale dynamicznie.
znane Obejścia
mogę obejść ten problem, albo korzystając bei std::stringstream
zamiast std::ostringstream
w źródle some.lib.Myślę, że mógłbym z tym żyć, ale dla każdego opiekuna trudno byłoby zrozumieć, dlaczego nie wolno mu używać ostringstreamu.
Alternatywnie, mógłbym użyć Linker-Flag /FORCE:MULTIPLE
dla some_test.exe i obniżyć wersję Error LNK2005 do Warning LNK4006. Ale nie lubię perma-ostrzeżeń, zwłaszcza jeśli są one tylko maskowanymi błędami.
pytań
Jaki jest właściwy sposób korzystać z boost_unit_test_framework i nie dostać te błędy linkera?
Czy w celu zwiększenia skuteczności celowo eksportujesz std::basic_ostringstream
, czy też powinienem wysłać zgłoszenie błędu?
Czy zadaję niewłaściwe pytania?
Rożne
Zachowanie MSVC wydaje się zmieniły w wersji 2010. Wcześniej nie było żadnych błędów. https://social.msdn.microsoft.com/Forums/vstudio/en-US/191de00a-53c9-4bd9-9cb6-e844eb224ca2/lnk2005-when-using-stdostringstream?forum=vclanguage
Po 8 dniach braku odpowiedzi lub komentarza na temat SO, otworzyłem wątek na liście mailingowej użytkownika boost. Jeśli odpowiedź zostanie znaleziona, oczywiście podzielę ją między SO a listą mailingową. http://lists.boost.org/boost-users/2016/06/86332.php (na dzień 17.08.2017 na liście adresowej nadal nie ma rozwiązania)
Teraz, rok później, zaktualizowałem program do wersji Visual Studio 2015 i otrzymałem takie samo zachowanie.
Wystarczy, aby mieć pewność, masz zdefiniowany symbol "BOOST_ALL_DYN_LINK"? – zahir
Miałem BOOST_TEST_DYN_LINK zdefiniowany dla some_test.exe, ale również przebudowałem i połącz z BOOST_ALL_DYN_LINK dla obu plików some.lib i some_test.exe. Trzy komunikaty o błędach pozostają takie same. – Sascha
Czy próbowałeś z VS 2015? Jeśli problem pojawił się w jednej wersji kompilatora, mógł zniknąć w innym. – eh9