Отладочная замена для make_shared () - PullRequest
3 голосов
/ 10 февраля 2012

Используя gcc 4.6.2, make_shared () дает бесполезную обратную трассировку (очевидно, из-за некоторого переброса), если конструктор выдает исключение. Я использую make_shared (), чтобы немного набрать текст, но это show stoppper. Я создал замену 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

Функция back_trace make_shared () - это мусор, который не показывает стек до точки исключения. Все остальные опции обеспечивают нормальную обратную трассировку.

Заранее спасибо за помощь и предложения.

1 Ответ

4 голосов
/ 11 февраля 2012

Ваша реализация 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)...));
}
...