2016-06-20 5 views
7

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.

+0

Wystarczy, aby mieć pewność, masz zdefiniowany symbol "BOOST_ALL_DYN_LINK"? – zahir

+0

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

+0

Czy próbowałeś z VS 2015? Jeśli problem pojawił się w jednej wersji kompilatora, mógł zniknąć w innym. – eh9

Odpowiedz

0

Założę się, że twoje ciągnięcie w dwóch różnych środowiskach C. Jeden doładuj, a drugi do swojego projektu. Proszę sprawdzić swój projekt some_test.exe-> Właściwości konfiguracji-> C/C++ -> Generowanie kodu -> Runtime Library i wypróbować wielowątkową bibliotekę DLL.

+0

Sprawdziłem ustawienie (po raz setny :-)).Jest już ustawione na/MD we wszystkich projektach. – Sascha

0

Przez Googling problem, znalazłem następujące propozycje, jeśli mogą one pomóc


Dodaj do zależeć projektach makro z BOOST_ALL_NO_LIB aw głównej projektu dodaj do linkera wprowadzania niezbędnych bibliotek. add/FORCE: WIELU opcji linku komend linera.

Od MSDN: "Użyj/FORCE: MULTIPLE, aby utworzyć plik wyjściowy niezależnie od tego, czy LINK znajdzie więcej niż jedną definicję symbolu."

Spróbuj tego:

Opcja --build-type=complete przyczyny Zwiększ Budowanie zbudować wszystkie obsługiwane warianty bibliotek. Użyj debugowania przy użyciu /MTd.

Można również zasięgnąć this page

+0

Wypróbowałem Twoją sugestię za pomocą BOOST_ALL_NO_LIB, ale to nie zmienia błędów. Jak wspomniałem w pytaniu,/FORCE: MULTIPLE zmienia stały błąd na stałe ostrzeżenie. Chcę, aby mój kod był kompilowany bez ostrzeżeń. – Sascha

Powiązane problemy