Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Работа деструктора при исключениях, Как правильно уничтожить объект 
V
    Опции темы
wrathchildtoo
Дата 24.9.2009, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 6.4.2009

Репутация: нет
Всего: нет



Привет всем.
Как же всё-таки правильно размотать стек, если возникает исключительная ситуация в конструкторе. На сколько я понял при этом не вызывается деструктор объекта, в конструкторе которого возникло исключение.

Например:
Код
#include<new>
using std::bad_alloc;

class A
{
private:
    char *ptr1;
    char *ptr2;
    
public:
    A()
    {
        ptr1 = new char[10]; //допустим тут всё прошло без ошибок
        ptr2 = new char[10]; //а тут возникла исключительная ситуация
    }
    ~A()
    {
        delete []ptr1;
        delete []ptr2;
    }
};

int main()
{
    try
    {
        A obj;
    }
    catch(bad_alloc)
    {
        //doing something
    }
    
    return 0;
}


Как освободить память, на которую указывает ptr1? Или же существуют какие-то автоматические механизмы, которые освободят память?
PM MAIL   Вверх
Lazin
Дата 24.9.2009, 14:21 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



Цитата(wrathchildtoo @  24.9.2009,  13:37 Найти цитируемый пост)
На сколько я понял при этом не вызывается деструктор объекта, в конструкторе которого возникло исключение.

вызовется
Цитата(wrathchildtoo @  24.9.2009,  13:37 Найти цитируемый пост)
Или же существуют какие-то автоматические механизмы, которые освободят память? 

Код

class A
{
private:
    std::vector<char> ptr1;
    std::vector<char> ptr2;
    
public:
    A() : ptr1(10), ptr2(10)
    {
    }
};

или 

class A
{
private:
    char *ptr1;
    char *ptr2;
    
public:
    A() : ptr1(0), ptr2(0)
    {
        ptr1 = new char[10]; //допустим тут всё прошло без ошибок
        ptr2 = new char[10]; //а тут возникла исключительная ситуация
    }
    ~A()
    {
        delete []ptr1;
        delete []ptr2;  // в случае, если оператор new в конструкторе бросит исключение, указатель будет равен 0
    }
};

это то-же должно работать, так как delete 0 - вполне законная операция

Это сообщение отредактировал(а) Lazin - 24.9.2009, 16:28
PM MAIL Skype GTalk   Вверх
wrathchildtoo
Дата 24.9.2009, 14:35 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 6.4.2009

Репутация: нет
Всего: нет



Цитата(Lazin @ 24.9.2009,  14:21)
Цитата(wrathchildtoo @  24.9.2009,  13:37 Найти цитируемый пост)
На сколько я понял при этом не вызывается деструктор объекта, в конструкторе которого возникло исключение.

вызовется

Почему тогда при выполнении следующего кода:
Код
#include<iostream>
using std::cout;

class A
{
public:
    A()
    {
        cout << "Constructor of class A\n";
        throw int();
    }
    ~A()
    {
        cout << "Destructor of class A\n";
    }
};

int main()
{
    try
    {
        A obj;
    }
    catch(int)
    {
        cout << "Catching int\n";
    }
    
    return 0;
}


строка "Destructor of class A\n" не выводится на экран?
Цитата
Constructor of class A
Catching int
Press any key to continue . . .

PM MAIL   Вверх
Lazin
Дата 24.9.2009, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



Цитата(15.2 Constructors and destructors)

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.

видимо, если искл. брошено в конструкторе, то объект является частично сконструированным
PM MAIL Skype GTalk   Вверх
wrathchildtoo
Дата 24.9.2009, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 6.4.2009

Репутация: нет
Всего: нет



Кажецо нашел ответ на свой вопрос

Цитата
[17.4] How should I handle resources if my constructors may throw exceptions?

Every data member inside your object should clean up its own mess. 

If a constructor throws an exception, the object's destructor is not run. If your object has already done something that needs to be undone (such as allocating some memory, opening a file, or locking a semaphore), this "stuff that needs to be undone" must be remembered by a data member inside the object. 

For example, rather than allocating memory into a raw Fred* data member, put the allocated memory into a "smart pointer" member object, and the destructor of this smart pointer will delete the Fred object when the smart pointer dies. The template std::auto_ptr is an example of such as "smart pointer." You can also write your own reference counting smart pointer. You can also use smart pointers to "point" to disk records or objects on other machines. 

By the way, if you think your Fred class is going to be allocated into a smart pointer, be nice to your users and create a typedef within your Fred class:
Код
 #include <memory>
 
 class Fred {
 public:
   typedef std::auto_ptr<Fred> Ptr;
   ...
 };

That typedef simplifies the syntax of all the code that uses your objects: your users can say Fred::Ptr instead of std::auto_ptr<Fred>:
Код
 #include "Fred.h"
 
 void f(std::auto_ptr<Fred> p);  // explicit but verbose
 void f(Fred::Ptr           p);  // simpler
 
 void g()
 {
   std::auto_ptr<Fred> p1( new Fred() );  // explicit but verbose
   Fred::Ptr           p2( new Fred() );  // simpler
   ...
 }

Lazin, спасибо за помощь

Это сообщение отредактировал(а) wrathchildtoo - 24.9.2009, 17:28
PM MAIL   Вверх
ller
Дата 24.9.2009, 17:25 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 325
Регистрация: 4.8.2008
Где: г. Таганрог

Репутация: 2
Всего: 4



Обвернуть все выделение памяти в  try   catch и там уже разбираться что же произошло....
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1404 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.