3

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

我担心的是:

  1. make_shared() 下的不良回溯不知何故是我自己的错
  2. 我的替代品 make_shrd() 会给我带来一些微妙的问题。

这是一个演示:

#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() 回溯是垃圾,不会显示堆栈到异常点。所有其他选项都提供了合理的回溯。

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

4

1 回答 1

4

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

  1. 它避免了重复编写类型(如果分配的类型和期望的类型std::shared_ptr<T>相同,而不是后者用于基类)
  2. 它将共享对象的分配和对象的描述符组合成一个分配

的主要目的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)...));
}
于 2012-02-10T20:40:58.780 回答