Search code examples
c++c++11gdbshared-ptrcoredump

if constructor crashes from call to std::make_shared, can gdb show details of crash


In the below code, I am calling make_shared<MyClass>, and the constructor of MyClass throws an exception. If the core file is available, is it possible to find out the origin of crash [e.g.: whether the crash was from foo() or fun()] with the help of gdb?

#include <iostream>
#include <memory>
using namespace std;

class MyClass
{
    public:
        MyClass()
        {
            foo();
            fun();
        }

        ~MyClass() { }

        void foo()
        {
            throw("error 1");
        }
        void fun()
        {
            throw("error 2");
        }
};


shared_ptr<MyClass> createMyClass()
{
    return make_shared<MyClass>();
}

int main()
{
    shared_ptr<MyClass> c = createMyClass();
    return 0;
}

backtrace just points to this line:

 29     return make_shared<MyClass>();

backtrace:

Program received signal SIGABRT, Aborted.
0x00007ffff722d5f7 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.6.x86_64 libgcc-4.8.5-4.el7.x86_64 libstdc++-4.8.5-4.el7.x86_64

    (gdb) bt
    #0  0x00007ffff722d5f7 in raise () from /lib64/libc.so.6
    #1  0x00007ffff722ece8 in abort () from /lib64/libc.so.6
    #2  0x00007ffff7b329d5 in __gnu_cxx::__verbose_terminate_handler() () from /lib64/libstdc++.so.6
    #3  0x00007ffff7b30946 in ?? () from /lib64/libstdc++.so.6
    #4  0x00007ffff7b30973 in std::terminate() () from /lib64/libstdc++.so.6
    #5  0x00007ffff7b30be9 in __cxa_rethrow () from /lib64/libstdc++.so.6
    #6  0x000000000040121e in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<MyClass, std::allocator<MyClass>>(std::_Sp_make_shared_tag, MyClass*, std::allocator<MyClass> const&) (this=0x7fffffffe178, __a=...) at /usr/include/c++/4.8.2/bits/shared_ptr_base.h:509
    #7  0x00000000004010ba in std::__shared_ptr<MyClass, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<MyClass>>(std::_Sp_make_shared_tag, std::allocator<MyClass> const&) (this=0x7fffffffe170, __tag=..., __a=...) at /usr/include/c++/4.8.2/bits/shared_ptr_base.h:957
    #8  0x0000000000401052 in std::shared_ptr<MyClass>::shared_ptr<std::allocator<MyClass>>(std::_Sp_make_shared_tag, std::allocator<MyClass> const&) (this=0x7fffffffe170,
        __tag=..., __a=...) at /usr/include/c++/4.8.2/bits/shared_ptr.h:316
    #9  0x0000000000400f98 in std::allocate_shared<MyClass, std::allocator<MyClass>>(std::allocator<MyClass> const&) (__a=...) at /usr/include/c++/4.8.2/bits/shared_ptr.h:598
    #10 0x0000000000400ee0 in std::make_shared<MyClass<> > () at /usr/include/c++/4.8.2/bits/shared_ptr.h:614
    #11 0x0000000000400ce3 in createMyClass () at abrt.cpp:29
    #12 0x0000000000400cfe in main () at abrt.cpp:34
    (gdb) q

Solution

  • That information is lost by the time the core file is generated. The reason is that the shared_ptr constructor has to catch any exceptions from the object constructor in order to be able to deallocate the memory it allocated earlier (to prevent leaks induced by constructors that throw). By the time it catches the exception to deallocate the memory it no longer knows where in the constructor the exception was thrown.