2011-01-26 14 views
6

Kompiluję projekt używając Cygwin (GCC v4.5.0) i mam dziwny problem z linkerem. Mam nadzieję, że komuś, kto ma jakąś wiedzę, może pomóc.C++ łączenie bibliotek STD z różnymi standardami C++

Error: undefined reference to std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&&)

Jednak tylko łączenie zawiedzie kiedy mogę skompilować z gcc flagi kompilatora: -std=c++0x Udaje kiedy nie przewidują normy.

Kilka uwag:

  1. jestem informując gcc połączyć biblioteki standardowej ręcznie z flagą kompilatora: -lstdc++
  2. Zależność symbol jest pochodząca z pliku nagłówka biblioteki doładowania (v.1.45.0) : boost::units::detail::utility.hpp, function: std::string demangle(const char* name);
  3. Aplikacja kompiluje i łączy poprawnie używając MinGW gcc v4.5.0.

Pytania:

  1. Czy skompilowana biblioteka standardowa zazwyczaj zawierają różne symbole dla różnych standardów C++?
  2. Czy nazwa makra symboli zmienia się z różnymi standardami C++ w GCC?
  3. Dlaczego linker nie może znaleźć symboli dla std::basic_string, skoro mogę zagwarantować, że znajdzie on libstdc++.a?

Z góry dziękuję wszystkim.

-JT

+0

Jest coś złego w tekście błędu. Czy zacytowałeś to bezpośrednio? To nie ma sensu. –

+0

@ Noah: Czy odnosisz się do "&&"? To wygląda jak notacja referencyjna rvalue z C++ 0x. –

Odpowiedz

8

Tak, oba nowe rewizje standardu i raportów technicznych dokonać wielu zmian w zawartości biblioteki standardowej. Funkcja, do której się odwołujesz (std::string 's konstruktor ruchu) jest nowo dodana w standardowej bibliotece C++ 0x.

Wersja standardu nie wpływa na wymazywanie nazw, chociaż wersja kompilatora działa, a nowsze kompilatory są potrzebne do lepszego wsparcia C++ 0x, więc może wydawać się, że jest ze sobą spokrewniona.

Prawdopodobnie używasz zbyt starej wersji libstdC++.

EDIT: Podstawowe rozwiązywanie problemów:

$ find /usr -name libstdc++.a 
/usr/lib/gcc/i686-pc-cygwin/4.5.0/libstdc++.a 

$ cygcheck -f /usr/lib/gcc/i686-pc-cygwin/4.5.0/libstdc++.a 
libstdc++6-devel-4.5.0-1 

$ nm -C /usr/lib/gcc/i686-pc-cygwin/4.5.0/libstdc++.a | grep basic_string | grep '&&' 
00000000 T std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string&&) 
00000000 T std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string&&) 
00000000 T std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::assign(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&&) 
00000000 T std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::basic_string(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&&) 
00000000 T std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::basic_string(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&&) 
00000000 T std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::operator=(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&&) 

To rzeczywiście wygląda trochę śmiesznie. Definicje dla std::wstring (tj. std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >) wyglądają prawidłowo, a wąskie wersje nie. Nazwa std::string nigdy nie powinna przetrwać etapu mordowania, ponieważ jest to tylko typedef.

Jednak uzyskać taki sam efekt na linux:

% find /usr -name libstdc++.a 
/usr/lib64/gcc/x86_64-pc-linux-gnu/3.4.6/libstdc++.a 
/usr/lib64/gcc/x86_64-pc-linux-gnu/3.4.6/32/libstdc++.a 
/usr/lib64/gcc/x86_64-pc-linux-gnu/4.5.2/libstdc++.a 
/usr/lib64/gcc/x86_64-pc-linux-gnu/4.5.2/32/libstdc++.a 

% nm -C /usr/lib64/gcc/x86_64-pc-linux-gnu/4.5.2/libstdc++.a | grep basic_string | grep '&&' 
0000000000000000 W std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string&&) 
0000000000000000 W std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string&&) 
0000000000000000 W std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::assign(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&&) 
0000000000000000 W std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::basic_string(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&&) 
0000000000000000 W std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::basic_string(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&&) 
0000000000000000 W std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::operator=(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&&) 
+0

Hmm .. więc to by wskazywało, że być może wersja GCC v.4.5.0 w Cygwin jest wadliwa? –

+1

Kiedy zainstalowałeś eksperymentalną wersję g ++, dostałeś również v4.5 'libstdC++ 6-devel'? Właśnie dodano do mojej odpowiedzi polecenia niezbędne do sprawdzenia tej wersji. –

+1

Ahh to naprawia. Wielkie dzięki Ben. Nie zainstalowałem libstdC++ 6-devel. Niefortunne jest to, że cygwin nie dostarcza więcej dokumentacji, aby proces był mniej podatny na błędy. –