No useful backtrace after uncaught exception in std::thread

Tobias Ringström tobias@ringis.se
Tue Nov 15 20:30:00 GMT 2011


I have a problem with uncaught exceptions in a std::thread. Normally 
when there's an uncaught exception, the backtrace in gdb will show where 
the actual exception was thrown. When using std::thread, the exception 
seems to be thrown from even before the thread's main function is 
called, making it almost impossible to find out what actually happened. 
An example should illustrace nicely:

    #include <stdexcept>
    #include <thread>
    void foo()
    {
         throw std::runtime_error("foo");
    }
    int
    main()
    {
         thread t(foo);
         t.join();
    }


Compile using "g++ -Wall -std=c++0x -g tmp.cpp", and run "gdb a.out":

    (gdb) r
    Starting program: /boris/home/tobias/a.out
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib64/libthread_db.so.1".
    [New Thread 0x7ffff7dc1700 (LWP 2427)]
    terminate called after throwing an instance of 'std::runtime_error'
       what():  foo

    Program received signal SIGABRT, Aborted.
    [Switching to Thread 0x7ffff7dc1700 (LWP 2427)]
    0x00000034906362a5 in raise () from /lib64/libc.so.6
    Missing separate debuginfos, use: debuginfo-install
    boost-thread-1.47.0-3.fc16.x86_64 glibc-2.14.90-14.x86_64
    libgcc-4.6.2-1.fc16.x86_64 libstdc++-4.6.2-1.fc16.x86_64
    (gdb) bt
    #0  0x00000034906362a5 in raise () from /lib64/libc.so.6
    #1  0x0000003490637bbb in abort () from /lib64/libc.so.6
    #2  0x000000349aabbf8d in __gnu_cxx::__verbose_terminate_handler()
    () from /usr/lib64/libstdc++.so.6
    #3  0x000000349aaba146 in ?? () from /usr/lib64/libstdc++.so.6
    #4  0x000000349aaba173 in std::terminate() () from
    /usr/lib64/libstdc++.so.6
    #5  0x000000349aa70bdb in ?? () from /usr/lib64/libstdc++.so.6
    #6  0x0000003490a07d90 in start_thread () from /lib64/libpthread.so.0
    #7  0x00000034906eeddd in clone () from /lib64/libc.so.6


As you can see, foo() is not in the backtrace. Now, if I use 
boost::thread (1.47.0) instead:

    #include <stdexcept>
    #include <thread>
    #include <boost/thread.hpp>
    void foo()
    {
         throw std::runtime_error("foo");
    }
    int
    main()
    {
         boost::thread t(foo);
         t.join();
    }

The backtrace in gdb now looks like this:

    #0  0x00000034906362a5 in raise () from /lib64/libc.so.6
    #1  0x0000003490637bbb in abort () from /lib64/libc.so.6
    #2  0x000000349aabbf8d in __gnu_cxx::__verbose_terminate_handler()
    () from /usr/lib64/libstdc++.so.6
    #3  0x000000349aaba146 in ?? () from /usr/lib64/libstdc++.so.6
    #4  0x000000349aaba173 in std::terminate() () from
    /usr/lib64/libstdc++.so.6
    #5  0x000000349aaba26e in __cxa_throw () from /usr/lib64/libstdc++.so.6
    #6  0x0000000000403039 in foo () at tmp2.cpp:6
    #7  0x0000000000405b1f in boost::detail::thread_data<void
    (*)()>::run (this=0x60a0d0)
         at /usr/include/boost/thread/detail/thread.hpp:61
    #8  0x00007ffff7dd5bf9 in ?? () from
    /usr/lib64/libboost_thread-mt.so.1.47.0
    #9  0x0000003490a07d90 in start_thread () from /lib64/libpthread.so.0
    #10 0x00000034906eeddd in clone () from /lib64/libc.so.6


That's more like it. Is the std::thread behaviour a bug, or am I missing 
something? Though the C++11 standard seems to allow the stack to be 
unwound before std::terminate is called, it exceptionally unhelpful. 
I've search but not been able to find any explanation.

I've tested this using both gcc 4.6.2 and 4.5.1 on Linux x64_64.

/Tobias



More information about the Gcc-help mailing list