Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > исключение в к онструкторе


Автор: Artemon 9.7.2011, 11:19
Код

class MyEx{};

class C1
{
public:
C1()
     {
     throw MyEx();
     }
};


void main()
{
    
    try
    {
    C1* c = new C1;   // <<<<<<<<<<<<<<<<<
    }
    catch(...)
    {
    }
  
}


Вопрос: будет утечка памяти ?


Автор: boostcoder 9.7.2011, 11:24
конечно.
ведь память сначала выделяется, и только потом выполняется конструктор.

Автор: Artemon 9.7.2011, 11:33
Дело в том, что на форуме натыкался на тему где какой-то товарищ доказывал, что не в таком случае неважно где память выделена на стеке или в куче, она будет всеравно освобождена.

Автор: boostcoder 9.7.2011, 11:34
вдай ему истину, товарищу тому  smile 

Автор: azesmcar 9.7.2011, 12:39
Цитата(Artemon @  9.7.2011,  11:19 Найти цитируемый пост)
Вопрос: будет утечка памяти ?

Нет, не будет.

Оператор new выделяет память, создает объект (вызывает конструктор) и при исключение очищает память, так-как создание объекта провалилось.

Добавлено через 2 минуты и 54 секунды
Цитата(Artemon @  9.7.2011,  11:33 Найти цитируемый пост)
Дело в том, что на форуме натыкался на тему где какой-то товарищ доказывал, что не в таком случае неважно где память выделена на стеке или в куче, она будет всеравно освобождена. 

Прав товарищ. Иначе любой выброс исключения из конструктора привел бы к утечке памяти.

Автор: boostcoder 9.7.2011, 12:43
Цитата(azesmcar @  9.7.2011,  12:39 Найти цитируемый пост)
Нет, не будет.

 smile 
полагаю, вам все же виднее...

Artemon, приношу свои извинения за дезинформацию. ибо ответил так, как знал сам.

Добавлено через 1 минуту и 1 секунду
Цитата(azesmcar @  9.7.2011,  12:39 Найти цитируемый пост)
при исключение очищает память

деструктор, я так полагаю, вызван не будет?

Автор: azesmcar 9.7.2011, 12:46
Цитата(boostcoder @  9.7.2011,  12:43 Найти цитируемый пост)
деструктор, я так полагаю, вызван не будет? 

Нет, ведь объект не был создан, но будут вызваны деструкторы для всех, полностью инициализированных членов.
Цитата

An object that is partially constructed or partially destroyed will have destructors executed for all of its
fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and
the destructor has not yet begun execution.

и это
Цитата

An object that is partially constructed or partially destroyed will have destructors executed for all of its
fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and
the destructor has not yet begun execution. Should a constructor for an element of an automatic array
throw an exception, only the constructed elements of that array will be destroyed. If the object or array was
allocated in a new-expression, the matching deallocation function (3.7.3.2, 5.3.4, 12.5), if any, is called to
free the storage occupied by the object.


главную мысль выделил красным, остальные привел, чтобы из контекста было понятно, что речь идет о выбросе исключения из конструктора, т.е. о частично инициализированных объектах.

Добавлено через 1 минуту и 47 секунд
Цитата(boostcoder @  9.7.2011,  11:24 Найти цитируемый пост)
ведь память сначала выделяется, и только потом выполняется конструктор. 

на самом деле да, но это выполняется в виде транзакции, т.е. при исключении происходит откат.

Автор: boostcoder 9.7.2011, 12:52
Цитата(azesmcar @  9.7.2011,  12:46 Найти цитируемый пост)
да, но это выполняется в виде транзакции, т.е. при исключении происходит откат.

впервые слышу... smile 
просто у меня откуда-то сформированное правило: не писать в конструкторе то, что может выбросить исключение.

понял. спасибо.

Автор: azesmcar 9.7.2011, 12:54
Цитата(boostcoder @  9.7.2011,  12:52 Найти цитируемый пост)
просто у меня откуда-то сформированное правило: не писать в конструкторе то, что может выбросить исключение.

вот из деструктора действительно не стоит
Цитата

The process of calling destructors for automatic objects constructed on the path from a try block to a
throw-expression is called “stack unwinding.” [Note: If a destructor called during stack unwinding exits
with an exception, terminate is called (15.5.1). So destructors should generally catch exceptions and
not let them propagate out of the destructor.


а генерировать исключение в конструкторе вполне нормально, более того, это единственный способ сообщить об ошибке выполнения конструктора.

Автор: mes 9.7.2011, 13:12
Цитата(boostcoder @  9.7.2011,  11:52 Найти цитируемый пост)
просто у меня откуда-то сформированное правило: не писать в конструкторе то, что может выбросить исключение.

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

Автор: azesmcar 9.7.2011, 13:13
Цитата(mes @  9.7.2011,  13:12 Найти цитируемый пост)
должно быть правило, чтоб перед выкидом исключения не было "висячих" объектов (т.е. тех которые при раскрутке стека не удалятся, например голые указатель на new-созданный объект).. 

...и да поможет тебе RAII smile 

Автор: Artemon 9.7.2011, 14:17
Цитата(mes @  9.7.2011,  13:12 Найти цитируемый пост)
должно быть правило, чтоб перед выкидом исключения не было "висячих" объектов (т.е. тех которые при раскрутке стека не удалятся, например голые указатель на new-созданный объект)..


Не совсем  понятна фраза. Можно раскрыть мысль ?

Автор: Earnest 9.7.2011, 14:46
В приведенном в первом посте примере предполагается, что исключение может возникнуть из-за неудачного выделения памяти. Представим, что там 2 указателя, по которым память выделяется, а не один. И для первого все выделилось успешно, а для второго - нет. Тогда утечка будет (по первому), т.к. указатели голые, и никто им delete не вызовет.
Кстати, в твоем примере она будет по-любому, без всяких исключений, т.к. ты выделяешь память для временного объекта, который потом теряется. Если буквально смотреть на код.

Автор: Artemon 9.7.2011, 15:01
Цитата(Earnest @  9.7.2011,  14:46 Найти цитируемый пост)
В приведенном в первом посте примере предполагается, что исключение может возникнуть из-за неудачного выделения памяти. Представим, что там 2 указателя, по которым память выделяется, а не один. И для первого все выделилось успешно, а для второго - нет. Тогда утечка будет (по первому), т.к. указатели голые, и никто им delete не вызовет.


Понятно.

Спасибо всем за ответы, думаю тема исчерпана.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)