Страницы

Поиск по вопросам

среда, 29 января 2020 г.

Будет ли утечка памяти, если конструктор бросит исключение?

#память #cpp


Есть некая фабрика:

TBar * foo()
{
    return new TBar();  // здесь конструктор TBar бросает исключение
}


Если конструктор TBar бросит исключение, мы получим утечку памяти, выделенной для
нового объекта TBar. Верно?
    


Ответы

Ответ 1



Нет, неверно. Если не рассматривать выделения памяти внутри конструктора TBar, то утечек не будет. В языке C++ объект считается созданным только в тот момент, когда его конструктор завершит выполнение без ошибок. Здесь этого не происходит, поэтому объект никогда не был создан, а, значит, и память под него "как бы" не выделялась. Т.е. компилятор обязан корректно освободить память, в которой будет находится объект, в случае исключения в его конструкторе.

Ответ 2



Вот что написано в стандарте С++ 2011 15.2.2 An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object’s destructor will be invoked. If the object was allocated in a new-expression, the matching deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object. В общем, если конструктор был прерван исключением, то вызываются деструкторы всех уже созданных объектов, а динамическая память, выделенная под основной класс, будет освобождена соответствующим delete. Итого, утечки не будет, в том числе и при наличии базового класса, если, конечно, нет внутренних утечек памяти.

Ответ 3



Утечка будет, если у класса TBar есть хотя бы один базовый класс. В этом случае, если будет брошено исключение в конструкторе TBar, то деструкторы для всех базововых классов вызваны не будут. Поскольку объект еще полностью не был создан. Если есть опасение, что в конструкторе будет сгенерировано исключение и это приведет к фатальным последствиям для программы, то рекомендуется весь код всех конструкторов помещать в блог try. И придумать способ извещения о корректности создания объекта (типа IsValid()). TBar::TBar() { try { ... } catch (...) { } }

Ответ 4



Если исключение на перехватывать, то утечки не будет, так как программа аварийно завершится, если же его просто как-нибудь обработать, то утечка будет по понятным причинам, а если его обработать правильно (с очисткой памяти), то утечки тоже не будет. имхо

Комментариев нет:

Отправить комментарий