make_shared()的可调试替换

时间:2012-02-10 19:08:10

标签: c++ c++11 shared-ptr backtrace make-shared

使用gcc 4.6.2,如果构造函数抛出异常,make_shared()会给出无用的回溯(显然是由于某些重新抛出)。我正在使用make_shared()来节省一些打字,但这是显示停止。我创建了一个允许正常回溯的替换 make_shrd()。我正在使用gdb 7.3.1。

我很担心:

  1. make_shared()下的错误回溯是某种方式我自己的错误
  2. 我的替代品make_shrd()会给我带来微妙的问题。
  3. 这是一个演示:

    #include <memory>
    #include <stdexcept>
    
    using namespace std;
    
    class foo1
    {
    public:
            foo1( const string& bar, int x ) :m_bar(bar), m_x(x)
            {
                    throw logic_error( "Huh?" );
            }
            string m_bar;
            int m_x;
    };
    
    class foo2
    {
    public:
            foo2( const string& bar, int x ) : m_foo1(bar,x)
            {}
    
            foo1  m_foo1;
    };
    
    // more debuggable substitute for make_shared() ??
    template<typename T, typename... Args>
    std::shared_ptr<T> make_shrd( Args... args )
    {
            return std::shared_ptr<T>( new T(args...));
    }
    
    int main()
    {
            auto p_foo2 = make_shared<foo2>( "stuff", 5 );          // debug BAD!!
    //      auto p_foo2 = make_shrd<foo2>( "stuff", 5 );            // debug OK
    //      auto p_foo2 = new foo2( "stuff", 5 );                   // debug OK
    //      auto p_foo2 = shared_ptr<foo2>(new foo2( "stuff", 5 )); // debug OK
            return (int)(long int)p_foo2;
    }
    

    编译:

    g++ -g -std=c++0x -Wall -Wextra main.cpp
    

    调试:

    gdb a.out
    

    make_shared()回溯是垃圾,它不会将堆栈显示到异常点。所有其他选项都提供了理智的回溯。

    提前感谢您的帮助和建议。

1 个答案:

答案 0 :(得分:4)

make_shrd()的实现失去了只分配一块内存的能力:std::make_shared()做了两件事:

  1. 它避免重复写入类型(如果分配的类型和所需的std::shared_ptr<T>的类型相同而不是后者用于基类)
  2. 它将共享对象和对象描述符的分配合并为一个分配
  3. std::make_shared()的主要目的实际上是第二个功能。我没有看过实现,但我怀疑这也是导致你出现问题的部分。除此之外,我没有看到任何理由为什么你的实现在修复转发参数后更糟糕了:

    template<typename T, typename... Args>
    std::shared_ptr<T> make_shrd(Args&&... args)
    {
        return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
    }