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()、メモリのチャンクを 1 つだけ割り当てる機能が失われます。次のstd::make_shared()2 つのことを行います。

  1. タイプの記述の重複を回避します(割り当てのタイプと目的のタイプがstd::shared_ptr<T>基本クラスの場合ではなく、同じである場合)
  2. 共有オブジェクトの割り当てとオブジェクトの記述子を 1 つの割り当てに結合します。

の主な目的は、std::make_shared()実際には 2 番目の機能です。実装は見ていませんが、これが実際に問題を引き起こす部分でもあると思います。それ以外に、引数の転送を修正すると、実装が悪化する理由はわかりません。

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 に答える