Questions about CUDA-cum-Boost interaction occasionally pop up her on SO, but they are always (?) about compilation: CUDA has trouble with Boost's voodoo tricks. The common wisdom is to isolate your code using Boost from your CUDA-compiled code.
So, I've done this: I'm writing a small CUDA utility, with boost::program_options nicely limited to use in the implementation of a single class. My problems are in linking.
I'm working on Debian Stretch (64-bit), which is built with GCC 5.x (and this includes its Boost 1.58 packages). My local installation of CUDA 7.5, however, can only stomach gcc 4.9.x or earlier, which is what I use. After compiling everything, Undefined references remain. That is, after I do:
/usr/bin/g++-4.9 -Wall -std=c++11 originally_cu.o originaly_cpp.o weird_cmake_generated_intermediate_link.o -o foo_app -rdynamic /usr/local/cuda/lib64/libcudart_static.a -lpthread -lrt -ldl -lboost_log -lboost_system -lboost_program_options /usr/local/cuda/lib64/libcudart_static.a -lpthread -lrt -ldl -lboost_log -lboost_system -lboost_program_options
(CMake generates that, I'm not sure why I'm seeing the double -ls)
I get:
originally_cpp.o: In function `FooConfiguration::getFromProgramArguments(int, char**)':
FooConfiguration.cpp:(.text+0x5d4): undefined reference to `boost::program_options::options_description::options_description(std::string const&, unsigned int, unsigned int)'
FooConfiguration.cpp:(.text+0x6ca): undefined reference to `boost::program_options::options_description::options_description(std::string const&, unsigned int, unsigned int)'
FooConfiguration.cpp.o: In function `boost::program_options::validation_error::validation_error(boost::program_options::validation_error::kind_t, std::string const&, std::string const&, int)':
FooConfiguration.cpp:(.text._ZN5boost15program_options16validation_errorC2ENS1_6kind_tERKSsS4_i[_ZN5boost15program_options16validation_errorC5ENS1_6kind_tERKSsS4_i]+0x2e): undefined reference to `boost::program_options::validation_error::get_template(boost::program_options::validation_error::kind_t)'
et cetera.
I thought maybe this had something to do with the fact that Boost was built with gcc 5.x ; so, I downloaded Boost 1.60, built it with gcc 4.9, and installed it under /opt/boost (Edit: and add /opt/boost/lib to `LD_LIBRARY_PATH). But when I tried to use it, well - it builds, but I get segmentation violations within Boost (And I know I shouldn't, because the same code runs on another machine, at least to the point of parsing command-line arguments). Here's a backtrace from gdb:
(gdb) bt
#0 0x00007fe9b8362880 in boost::program_options::validators::check_first_occurrence(boost::any const&) () from /opt/boost/lib/libboost_program_options.so.1.60.0
#1 0x000000000046c9d8 in void boost::program_options::validate<int, char>(boost::any&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, int*, long) ()
#2 0x000000000046be44 in boost::program_options::typed_value<int, char>::xparse(boost::any&, std::vector<std::string, std::allocator<std::string> > const&) const ()
#3 0x00007fe9b8347cda in boost::program_options::option_description::~option_description() () from /opt/boost/lib/libboost_program_options.so.1.60.0
#4 0x00007fe9b834d2b5 in boost::detail::sp_counted_impl_p<boost::program_options::option_description>::dispose() () from /opt/boost/lib/libboost_program_options.so.1.60.0
#5 0x00000000004616d4 in boost::detail::sp_counted_base::release() ()
#6 0x0000000000461763 in boost::detail::shared_count::~shared_count() ()
#7 0x0000000000468c4c in boost::shared_ptr<boost::program_options::option_description>::~shared_ptr() ()
#8 0x0000000000468c66 in void std::_Destroy<boost::shared_ptr<boost::program_options::option_description> >(boost::shared_ptr<boost::program_options::option_description>*) ()
#9 0x0000000000467c05 in void std::_Destroy_aux<false>::__destroy<boost::shared_ptr<boost::program_options::option_description>*>(boost::shared_ptr<boost::program_options::option_description>*, boost::shared_ptr<boost::program_options::option_description>*) ()
#10 0x0000000000465eeb in void std::_Destroy<boost::shared_ptr<boost::program_options::option_description>*>(boost::shared_ptr<boost::program_options::option_description>*, boost::shared_ptr<boost::program_options::option_description>*) ()
#11 0x0000000000464337 in void std::_Destroy<boost::shared_ptr<boost::program_options::option_description>*, boost::shared_ptr<boost::program_options::option_description> >(boost::shared_ptr<boost::program_options::option_description>*, boost::shared_ptr<boost::program_options::option_description>*, std::allocator<boost::shared_ptr<boost::program_options::option_description> >&) ()
#12 0x0000000000462ee3 in std::vector<boost::shared_ptr<boost::program_options::option_description>, std::allocator<boost::shared_ptr<boost::program_options::option_description> > >::~vector() ()
#13 0x0000000000461ccc in boost::program_options::options_description::~options_description() ()
#14 0x000000000045fb88 in FooConfiguration::getFromProgramArguments(int, char**) ()
#15 0x00000000004710e1 in get_configuration (argc=1, argv=0x7fff61fcb398) at /home/joeuser/foo_app/src/main.cu:257
#16 0x00000000004711f7 in main (argc=1, argv=0x7fff61fcb398) at /home/joeuser/foo_app/src/main.cu:269
Here is the ldd output in this case:
linux-vdso.so.1 (0x00007ffd4912f000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f06496e6000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f06494de000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f06492d9000)
libboost_log.so.1.60.0 => /opt/boost/lib/libboost_log.so.1.60.0 (0x00007f064901e000)
libboost_system.so.1.60.0 => /opt/boost/lib/libboost_system.so.1.60.0 (0x00007f0648e1b000)
libboost_program_options.so.1.60.0 => /opt/boost/lib/libboost_program_options.so.1.60.0 (0x00007f0648ba3000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f0648828000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0648523000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f064830c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0647f68000)
/lib64/ld-linux-x86-64.so.2 (0x000055a192443000)
libboost_atomic.so.1.60.0 => /opt/boost/lib/libboost_atomic.so.1.60.0 (0x00007f0647d66000)
libboost_date_time.so.1.60.0 => /opt/boost/lib/libboost_date_time.so.1.60.0 (0x00007f0647b54000)
libboost_filesystem.so.1.60.0 => /opt/boost/lib/libboost_filesystem.so.1.60.0 (0x00007f064793b000)
libboost_regex.so.1.60.0 => /opt/boost/lib/libboost_regex.so.1.60.0 (0x00007f064761e000)
libboost_thread.so.1.60.0 => /opt/boost/lib/libboost_thread.so.1.60.0 (0x00007f06473f9000)
libboost_chrono.so.1.60.0 => /opt/boost/lib/libboost_chrono.so.1.60.0 (0x00007f06471f3000)
libicudata.so.55 => /usr/lib/x86_64-linux-gnu/libicudata.so.55 (0x00007f064573c000)
libicui18n.so.55 => /usr/lib/x86_64-linux-gnu/libicui18n.so.55 (0x00007f06452d9000)
libicuuc.so.55 => /usr/lib/x86_64-linux-gnu/libicuuc.so.55 (0x00007f0644f45000)
So:
What's causing these problems?
What can I do to either resolve them or circumvent them, other than not using Boost?
Apparently this has nothing to do with CUDA, I can get the problem to manifest with just Boost. Following up with the pertinent non-CUDA-related question. Thanks #Drop.
Related
When I attempt to use std::filesystem::path as a function argument, it segfaults on my machine. Here is a minimal example:
#include <filesystem>
void thing(const std::filesystem::path& p) {
return;
}
int main() {
thing("test");
return 0;
}
This snippet results in the following backtrace from gdb:
#0 0x0000563a5a3814b3 in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector (this=0x23, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/stl_vector.h:567
#1 0x0000563a5a38132c in std::filesystem::__cxx11::path::~path (this=0x3, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/fs_path.h:208
#2 0x0000563a5a381f74 in std::filesystem::__cxx11::path::_Cmpt::~_Cmpt (this=0x3, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/fs_path.h:643
#3 0x0000563a5a381f8f in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt> (__pointer=0x3) at /usr/include/c++/8/bits/stl_construct.h:98
#4 0x0000563a5a381e3f in std::_Destroy_aux<false>::__destroy<std::filesystem::__cxx11::path::_Cmpt*> (__first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:108
#5 0x0000563a5a381ab0 in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt*> (__first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:137
#6 0x0000563a5a3817c1 in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt*, std::filesystem::__cxx11::path::_Cmpt> (__first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:206
#7 0x0000563a5a3814c9 in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector (this=0x7ffd198df8a0 = {...}, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/stl_vector.h:567
#8 0x0000563a5a38132c in std::filesystem::__cxx11::path::~path (this=0x7ffd198df880<error reading variable: Cannot access memory at address 0x2b>, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/fs_path.h:208
#9 0x0000563a5a381247 in main () at /home/user/CLionProjects/test/main.cpp:8
#10 0x00007fd6bb96ab6b in __libc_start_main (main=0x563a5a381200 <main()>, argc=1, argv=0x7ffd198df9b8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffd198df9a8) at ../csu/libc-start.c:308
#11 0x0000563a5a38113a in _start ()
I am using GCC 8.3 on Ubuntu 19.10, I had someone else compile and run this code with no issues on Windows so it could potentially be a bug in libstdc++
I think the problem is that Ubuntu mixes GCC versions in a single installation. On Ubuntu the default GCC is version 8, but the libstdc++.so.6 library comes from GCC 9. With GCC 8 the std::filesystem definitions are in a separate library, libstdc++fs.a, which must be linked to explicitly. In GCC 9 the std::filesystem symbols are in the main libstdc++.so library. Because of the mixed up Ubuntu installation it's possible for the GCC 9 symbols in libstdc++.so to satisfy the undefined references in code compiled with GCC 8 which should be satisfied by libstdc++fs.a. Because the std::filesystem symbols in GCC 9 are incompatible with the experimental versions of those symbols in GCC 8, it appears to link OK but crashes at runtime.
It should work correctly if you make sure you link with -lstdc++fs and make sure that option comes after all your object files, e.g. this should work:
g++ foo.o bar.o -lstdc++fs
But this will not work:
g++ -lstdc++fs foo.o bar.o
There is supposed to be an update to the Ubuntu gcc-8 packages to fix this, by ensuring the -lstdc++fs option comes after all the other input files. For more details see https://bugs.launchpad.net/ubuntu/+source/gcc-8/+bug/1824721
Compiling with gcc-9 also works, because when using GCC 9 to compile there is no need to link to -lstdc++fs for std::filesystem (with GCC 9 it's only needed for std::experimental::filesystem symbols).
I was able to fix this issue by installing GCC and G++ 9 from this PPA: https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
Please link -lstdc++fs library, let's consider source file is fileSys.cpp then compile it as follows,
g++ -std=c++17 fileSys.cpp -lstdc++fs -o fs
I am using GCC 8.1.0 and Ubuntu 16.04.1 LTS.
There is already a similar question on this topic, you can find it at filesystem linker error
I tried to build webpage based on CppCMS. It compiles and works under Gentoo (GCC). But I have problems when trying to build application under FreeBSD (account on hosting provider). Default compiler is Clang.
I downloaded CppCMS package and exported few variables:
export CC=gcc48
export CXX=g++48
export LD_LIBRARY_PATH=/usr/local/lib/gcc48
Then as usual:
cmake -DCMAKE_INSTALL_PREFIX=/home/mrozigor/libs ..
make
And at this moment something is probably wrong, because it fails on all tests (make test) with segmentation fault. But I tried to build my application and used command:
PATH=$HOME/libs/bin:$PATH CPATH=$HOME/libs/include:$CPATH LIBRARY_PATH=$HOME/libs/lib:$LIBRARY_PATH ./build.sh
and it build it. But when trying to exec it (LD_LIBRARY_PATH=$HOME/libs/lib app) it also fails with SEGFAULT.
What is also interesting when i tried to execute command ldd libcppcms.so in CppCMS build directory it fails with ldd: libcppcms.so: Shared object "libcppcms.so" not found, required by "ldd", but when trying same command in lib install directory then it points to proper objects.
Is this a problem with linking some libraries? Or maybe some env variables points to some Clang dependencies etc.?
[EDIT]
Tried with options:
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/home/mrozigor/libs -DCMAKE_C_COMPILER=gcc49 -DCMAKE_CXX_COMPILER=g++49 -DCMAKE_LIBRARY_PATH=/usr/local/lib/gcc49 ..
LD_LIBRARY_PATH=/usr/local/lib/gcc49 make
LD_LIBRARY_PATH=/usr/local/lib/gcc49
Still SEGFAULTs with given backtrace, based on dump file:
#0 0x0000000000000000 in ?? ()
#1 0x0000000802d3fc49 in __cxxabiv1::__dynamic_cast (src_ptr=0x80300f3c0 <(anonymous namespace)::ctype_c>, src_type=0x802ff35d0 <typeinfo for std::locale::facet>, dst_type=0x802ff3340 <typeinfo for std::ctype<char>>, src2dst=0) at /wrkdirs/usr/ports/lang/gcc/work/gcc-4.9.4/libstdc++-v3/libsupc++/dyncast.cc:60
#2 0x0000000802d76477 in std::has_facet<std::ctype<char> > (__loc=...) at /wrkdirs/usr/ports/lang/gcc/work/.build/x86_64-portbld-freebsd10.3/libstdc++-v3/include/bits/locale_classes.tcc:110
#3 0x0000000802d67658 in std::basic_ios<char, std::char_traits<char> >::_M_cache_locale (this=this#entry=0x606448 <std::cout##GLIBCXX_3.4+8>, __loc=...) at /wrkdirs/usr/ports/lang/gcc/work/.build/x86_64-portbld-freebsd10.3/libstdc++-v3/include/bits/basic_ios.tcc:159
#4 0x0000000802d67824 in std::basic_ios<char, std::char_traits<char> >::init (this=this#entry=0x606448 <std::cout##GLIBCXX_3.4+8>, __sb=0x80300d7c0 <__gnu_internal::buf_cout_sync>) at /wrkdirs/usr/ports/lang/gcc/work/.build/x86_64-portbld-freebsd10.3/libstdc++-v3/include/bits/basic_ios.tcc:132
#5 0x0000000802d56d51 in std::basic_ostream<char, std::char_traits<char> >::basic_ostream (__sb=<optimized out>, this=<optimized out>, __in_chrg=<optimized out>, __vtt_parm=<optimized out>) at /wrkdirs/usr/ports/lang/gcc/work/.build/x86_64-portbld-freebsd10.3/libstdc++-v3/include/ostream:85
#6 std::ios_base::Init::Init (this=<optimized out>) at /wrkdirs/usr/ports/lang/gcc/work/gcc-4.9.4/libstdc++-v3/src/c++98/ios_init.cc:91
#7 0x000000080112c941 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /usr/local/lib/gcc49/include/c++/iostream:74
#8 0x000000080112c98c in _GLOBAL__sub_I_posix_time.cpp(void) () at /home/mrozigor/src/cppcms/booster/lib/ptime/src/posix_time.cpp:101
#9 0x000000080060ab77 in ?? () from /libexec/ld-elf.so.1
#10 0x000000080060a0ee in ?? () from /libexec/ld-elf.so.1
#11 0x0000000800608439 in ?? () from /libexec/ld-elf.so.1
#12 0x0000000000000000 in ?? ()
I am working on some rather large C++ app, with most of the code being stored in a static library, and some programs that use that code.
I have what looks like a memory corruption run-time crash:
*** Error in `build/bin/myapp': malloc(): memory corruption (fast): 0x00000000021f62a0 ***
I want to check where that happens. GDB seems the right tool (OS: Ubuntu 14.04).
My makefiles handles both debug and release with a makefile command-line switch.
With the switch on, the -g flag is added and the .a library is 23.8 MB, while the app is 519 kB.
Without, its 1.6 MB and 486kB (so I'm pretty sure the debugging symbols are there).
My (partial) CFLAGS, as suggested by the gcc manual:
CFLAGS = -std=c++11 -g -Wall -O0 -fno-inline
I run gdb with:
gdb --args build/bin/myapp datafile.dat -a -b (...and more arguments)
My problem is that even in the debug build, gdb keeps telling me that it can't find any symbols:
Reading symbols from build/bin/myapp...(no debugging symbols found)...done.
If I run it from within gdb, it crashes with:
Program received signal SIGABRT, Aborted.
0x00007ffff5298cc9 in __GI_raise (sig=sig#entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
And the backtrace command shows indeed that symbols are missing: frames 10 to 18 have missing information, and are probably related to my code:
(gdb) bt
#0 0x00007ffff5298cc9 in __GI_raise (sig=sig#entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007ffff529c0d8 in __GI_abort () at abort.c:89
#2 0x00007ffff52d5394 in __libc_message (do_abort=do_abort#entry=1, fmt=fmt#entry=0x7ffff53e3b28 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007ffff52e00f7 in malloc_printerr (action=<optimized out>, str=0x7ffff53e3ec8 "malloc(): memory corruption (fast)", ptr=<optimized out>) at malloc.c:4996
#4 0x00007ffff52e2e04 in _int_malloc (av=0x7ffff5620760 <main_arena>, bytes=36) at malloc.c:3359
#5 0x00007ffff52e47b0 in __GI___libc_malloc (bytes=36) at malloc.c:2891
#6 0x00007ffff5babe68 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007ffff5c03e69 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8 0x000000000045a7a5 in char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) ()
#9 0x00007ffff5c05bd6 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#10 0x000000000042df7f in ?? ()
#11 0x000000000042eef6 in ?? ()
#12 0x0000000000421dab in ?? ()
#13 0x0000000000422223 in ?? ()
#14 0x0000000000422cfe in ?? ()
#15 0x0000000000423393 in ?? ()
#16 0x0000000000424600 in ?? ()
#17 0x000000000040fd50 in ?? ()
#18 0x000000000040566d in ?? ()
#19 0x00007ffff5283ec5 in __libc_start_main (main=0x4053c0, argc=6, argv=0x7fffffffddf8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffdde8) at libc-start.c:287
#20 0x000000000040604f in ?? ()
I did check some of the many questions about this topic, but none of any help (most of these relate to a forgotten -g flag, or an added -s, stripping down the symbols).
Question: what can the next step be to find out why/where my crash happens?
Additional info:
gcc --version: 5.3.0
gdb --version: 7.7.1
code dependencies: boost and opencv
but none of any help (most of these relate to a forgotten -g flag, or an added -s, stripping down the symbols).
It is almost certain that you either have a stray -s somewhere on your link line, or you run stip on the binary during installation.
Look at your link command line and install command carefully, there is strip somewhere in there.
P.S. As Tom Tromey already said, GDB is rarely effective in helping with a problem like this. Using Valgrind or Address Sanitizer will likely get you to the root cause much faster.
I have a shared library file which I build using a Makefile. I ran into an issue where, after building the library, I'd get the dreaded GLIBCXX_ not found linker error.
This case is particularly strange. When I compile with the -g3 flag, I don't get the error. If I compile with -O2, I get the error.
So, when I compile with -O2, and run ldd against the compiled .so file, I get:
$ ldd MYLIB.so.1
./MYLIB.so.1: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by ./MYLIB.so.1)
linux-vdso.so.1 => (0x00007fff21e8d000)
libz.so.1 => /lib64/libz.so.1 (0x00002b2cd4c40000)
libpng12.so.0 => /usr/lib64/libpng12.so.0 (0x00002b2cd4e54000)
libjpeg.so.62 => /usr/lib64/libjpeg.so.62 (0x00002b2cd5079000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00002b2cd529b000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00002b2cd54b7000)
libm.so.6 => /lib64/libm.so.6 (0x00002b2cd57b8000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002b2cd5a3b000)
libc.so.6 => /lib64/libc.so.6 (0x00002b2cd5c49000)
/lib64/ld-linux-x86-64.so.2 (0x0000003891400000)
So here, for some reason, /usr/lib64/libstdc++.so.6 is looking for GLIBCXX_3.4.9, which does not exist in /usr/lib64/libstdc++.so.6, as we can see using the strings utility:
$ strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_FORCE_NEW
So, to further investigate this, I run nm against the compiled .so file, and try to find what symbols are looking for GLIBCXX_3.4.9
$ nm --demangle MYLIB.so.1 | grep GLIBCXX_3.4.9
U std::ostream& std::ostream::_M_insert<unsigned long>(unsigned long)##GLIBCXX_3.4.9
U std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)##GLIBCXX_3.4.9
Okay, so it looks like some standard C++ ostream code requires GLIBCXX_3.4.9. Okay... but it's only this one symbol that seems to require GLIBCXX_3.4.9. Everything else correctly links with GLIBCXX_3.4:
$nm --demangle MYLIB.so.1 | grep GLIBCXX
U std::string::find(char const*, unsigned long, unsigned long) const##GLIBCXX_3.4
U std::string::compare(char const*) const##GLIBCXX_3.4
U std::string::compare(std::string const&) const##GLIBCXX_3.4
U std::logic_error::what() const##GLIBCXX_3.4
U std::runtime_error::what() const##GLIBCXX_3.4
U std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::str() const##GLIBCXX_3.4
U std::basic_iostream<char, std::char_traits<char> >::~basic_iostream()##GLIBCXX_3.4
... etc ...
So what could be the cause of this? Why would one particular symbol link GLIBCXX_3.4.9, but the rest don't? Even more strange - this only happens when I compile with -O2.
I'm pretty baffled by this. So, what are some likely reasons why this might occur? How does the linker/compiler chain determine which GLIBCXX version a particular symbol is found in?
This simply means you're compiling with a newer GCC than the /usr/lib64/libstdc++.so library belongs to, and you are not telling the dynamic linker how to find the right libstdc++.so
The reference to GLIBCXX_3.4.9 means you are compiling with at least GCC 4.2.0 but the system libstdc++.so is from an older version, 4.1.1 or 4.1.2.
The fact it's only a problem at -O2 is not really relevant, if you compile with a newer GCC you need to use its libstdc++.so, period. It seems that unless you compile with -O2 you don't actually get a hard dependency on the newer libstdc++.so but that's just chance, it could change if you make any small changes to your code that causes it to be optimised slightly differently.
You need to read https://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.how_to_set_paths and https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dynamic_or_shared.html#manual.intro.using.linkage.dynamic
Why would one particular symbol link GLIBCXX_3.4.9, but the rest don't?
Because the other symbols are unchanged between GCC 3.4 and 4.2 and the version of the symbol in your old libstdc++.so is the same as the one you linked against when building your executable.
The symbol that is not being found is something that was new in GCC 4.2, so it gets given a newer symbol version, and it can't be found in older libraries.
Pursuant to the post, Standalone functions/data in C++, I proceeded to put my "common data" in an anonymous namespace as below and everything worked great on Windows (Vista 64 bit) on VS 2005/2008/2010
namespace {
...
static std::string mystrings[] = {
str1,
str2,
...,
strN
};
...
}
namespace mynamesp {
...
use mystrings[] here..
...
}
But on Linux (so far tested RHEL5 built with GCC-4.1.2) I promptly got a segmentation fault.
$>myprog
Segmentation fault
$>gdb myprog
GNU gdb Fedora (6.8-27.el5)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu"...
(gdb) r
Starting program: <path/to>/myprog
[Thread debugging using libthread_db enabled]
[New Thread 0x2b8901a9da60 (LWP 32710)]
Program received signal SIGSEGV, Segmentation fault.
0x0000003e4ce9c928 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string ()
from /usr/lib64/libstdc++.so.6
(gdb) bt
#0 0x0000003e4ce9c928 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string ()
from /usr/lib64/libstdc++.so.6
#1 0x00002b88ffde482b in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535)
at <path/to>/mysource.cpp:140
#2 0x00002b88ffde4d65 in global constructors keyed to _ZN91_GLOBAL__N__underscore_separated_path_to_mysource.cpp_00000000_6994A7DA2_1E () at <path/to>/mysource.cpp:12139
#3 0x00002b890011a296 in __do_global_ctors_aux ()
from <path/to/libs>/debug/libmylibd.so
#4 0x00002b88ffcd7f33 in _init () from <path/to/libs>/debug/libmylibd.so
#5 0x00002b8901672e40 in ?? ()
#6 0x000000326940d22b in call_init () from /lib64/ld-linux-x86-64.so.2
#7 0x000000326940d335 in _dl_init_internal () from /lib64/ld-linux-x86-64.so.2
#8 0x0000003269400aaa in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#9 0x0000000000000001 in ?? ()
#10 0x0000000000000000 in ?? ()
(gdb)
Line 140 in the backtrace call stack item #1 basically points to the end of my array of strings definition. I've seen some others get this error; but no obvious fixes. Appreciate any thoughts/ideas/corrections as always. Thanks!
Your problem could be releated to a static initialization order fiasco.
This happens when you initialize a static variable using another static variable. When the latter one has not been initialized yet, then the first one is using a non-initialized variable for its initialization.
The root cause is that the order, in which static variables are initialized, is undefined.
Further reading:
https://isocpp.org/wiki/faq/ctors#static-init-order
A typical workaround would be to wrap the static variables inside a function. Example:
T& GetStaticA() {
T static_var_A; // <--initialization here
return A;
}
T static_var_B = GetStaticA(); // <-- static_var_A is guaranteed to be initialized
I had this problem and it turned out that in my compiling line I had missed the final output file in the linking.
g++ main.o logger.o timer.o keyboard.o -o main -lSDL -lSDL_image -lSDL_ttf -Wall
should have been
g++ main.o logger.o timer.o keyboard.o drawer.o -o main -lSDL -lSDL_image -lSDL_ttf -Wall
(Notice the now inclusion of drawer.o?)
It was easy to miss because my actual bash compilation script had many more lines to it.