I am compiling a project using Cygwin (GCC v4.5.0) and I'm having an odd linker problem. I am hoping somebody with some expertise can help.
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> >&&)
However, the linking only fails when I compile with the gcc compiler flag:
-std=c++0x
It succeeds when I don't specify the standard.
Some notes:
- I am informing gcc to link the standard library manually with the compiler flag:
-lstdc++
- The symbol dependency is originating from a Boost library header file (v.1.45.0):
boost::units::detail::utility.hpp, function: std::string demangle(const char* name);
- The application compiles and links properly using MinGW gcc v4.5.0.
Questions:
- Does the compiled standard library usually contain different symbols for different C++ standards?
- Does the name mangling of symbols change with different C++ standards in GCC?
- Why can't the linker find the symbols for
std::basic_string
when I can guarantee that it can find libstdc++.a
?
Thanks in advance everyone.
-JT
Yes, both new revisions of the standard and technical reports make many changes to the content of the standard library. The function you referenced (std::string
's move constructor) is newly added in C++0x's standard library.
The version of the standard does not affect name mangling, although the compiler version does, and newer compilers are needed for better C++0x support, so it could appear to be related.
You are probably using too old a version of libstdc++.
EDIT: Basic troubleshooting:
$ 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> >&&)
This does indeed look a little funny. The definitions for std::wstring
(i.e. std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >
) look correct, the narrow versions do not. The name std::string
shouldn't ever have survived to the mangling stage, since it's just a typedef.
However, I get the same output on 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> >&&)