Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.93/15: Рейтинг темы: голосов - 15, средняя оценка - 4.93
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447

Освобождение памяти при возникновения исключения в конструкторе

20.11.2018, 12:01. Показов 3200. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
class IScene{
public :
  virtual void Draw() const = 0;
}
 
class Scene: public IScene
{
/.../
}
C++
1
2
3
4
5
6
7
8
9
10
class Canvas{
   IScene _scene;
public :
  Canvas(IScene* scene){
      if(scene == nullptr)
            throw exception("scene is nullptr");
      
      _scene = scene;
  }
}
C++
1
2
3
Scene* scene = new Scene();
 
Cnavas canvas(/*scene*/nullptr);

Тапками если что сразу не кидайтесь если что написал неправильно) Вопрос возник при чтении книги Филлософия C++. Такой код я часто пишу пишу на C# при добавлении зависимости. Если передаваемое значение не указывает на экземпляр возникает исключение. Но сегодня я прочитал, что C++ это может приводить к аллокации памяти. Так ли это в данном случае, если в конструкторе возникнет исключение? Если да то как правильно очищать память при возникновении исключения?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.11.2018, 12:01
Ответы с готовыми решениями:

Освобождение памяти при исключениях и именованные исключения
Есть 2 вопроса, ответы чет не удалось загуглить 1)Каким образом выполняется освобождение памяти при возникновении исключительных ситуаций...

Выделение и освобождение памяти в конструкторе и деструкторе
Есть программа с классом содержащим обьекты векторы. Однако по кончанию программы выбивате ошибку _block_type_is_vali(phead->nblockuse)....

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

14
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
20.11.2018, 12:28
BaredJJ, вы бы хоть какой-то минимальный, но компилируемый пример привели...
А то вот и не понятно: то ли объяснять вам базовые вещи, то ли просто посоветовать вам почитать про умные указатели.

Добавлено через 50 секунд
И ответ на вопрос "зачем вам понадобились здесь динамические аллокации" тоже хотелось бы услышать.
0
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
20.11.2018, 12:54  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class IScene
{
protected:
    ~IScene() = default;
public:
    virtual void Draw() const = 0;
};
 
class Scene:public IScene
{
public:
    Scene();
    void Draw() const override;
    ~Scene();
};
 
#include "pch.h"
#include "Scene.h"
#include <ostream>
#include <iostream>
 
 
Scene::Scene()
{
}
 
 
void Scene::Draw() const
{
    std::cout << "Helloy" << std::endl;
}
 
 
Scene::~Scene()
{
}
 
class Canvas
{
    IScene* _scene;
public:
    Canvas(IScene* scene);
    ~Canvas();
};
 
#include "pch.h"
#include "Canvas.h"
#include <exception>
 
 
Canvas::Canvas(IScene* scene )
{
    if (scene == nullptr)
        throw std::exception("scene is nullptr");
 
    _scene = scene;
}
 
 
Canvas::~Canvas()
{
}
 
#include "pch.h"
#include <iostream>
#include "Scene.h"
#include "Canvas.h"
 
int main()
{
    Scene* scene = new Scene();
    Canvas canvas(scene);
    system("pause");
}
Написал и реально не компилируеутся Link 1104. Даже не понимаю в чем проблема. Я ж только учусь. Не судите строго.
Про умные указатели, только слышал, но это какой то холивар у некоторых вызывает) Мне просто интересно, что станет с объектом, если при его конструировании произойдет исключение?

Добавлено через 40 секунд
Да и что вы подразумеваете под динамическими аллокациями?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
20.11.2018, 13:01
BaredJJ,
Если конструктор бросил исключение, то обьект не считается созданным и деструктор для таких объектов не вызывается.
Соответственно если вы в конструкторе выделяли память и надеялись освободить её в деструкторе, то будет утечка памяти.
Если конструктор бросает исключение, то проектировать его надо с учётом вышесказанного
1
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
20.11.2018, 13:08  [ТС]
Цитата Сообщение от Undisputed Посмотреть сообщение
то проектировать его надо с учётом вышесказанного
Правильно ли я понимаю, что под этими словами подразумевается изначальная проверка валидности входных данных, а уж затем формирование внутренней структуры объекта? Или есть еще какие то особенности?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
20.11.2018, 13:16
Цитата Сообщение от BaredJJ Посмотреть сообщение
Да и что вы подразумеваете под динамическими аллокациями?
Создание объектов с динамическим размещением (dynamic storage duration). То, что вы сделали в 71 строке.

Цитата Сообщение от BaredJJ Посмотреть сообщение
но это какой то холивар у некоторых вызывает
Простите, но если у плотника инструмент "рубанок" вызывает холивар, то это какой-то неправильный плотник. Он говорит, что и стамесочкой все прекрасно сделает. Ну, прекрасно. Только вот инструмент (в данном случае рубанок) тут при чем?

Умный указатель - это совершенно естественный в рамках идеологии C++ способ обеспечить гарантию безопасности исключений при использовании динамических аллокаций. Этот способ соответствует главной идиоме C++ - RAII и является живой иллюстрацией ее возможностей. Можно, конечно, обойтись из без них, как и доски можно обработать стамеской, но в большинстве случае усилия будут несоизмеримы результату.

Цитата Сообщение от BaredJJ Посмотреть сообщение
не компилируеутся Link 1104.
Не линкуется. Ошибку полностью процитируйте.
0
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
20.11.2018, 13:31  [ТС]
Severity Code Description Project File Line Suppression State
Error LNK1104 cannot open file 'msvcprtd.lib' 1

Добавлено через 4 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
То, что вы сделали в 71 строке.
C++
1
2
3
4
5
6
int main()
{
    Scene scene = Scene();
    Canvas canvas(&scene);
    system("pause");
}
Так правильней?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
20.11.2018, 13:31
BaredJJ,
Просто помните что деструктор в случае исключения не будет вызван и учитывайте это.
С точки зрения ресурсов не важно где вы их освободите.
Главное что бы это соответствовало логике программы и не портило архитектуру.

Как это обеспечить? Да по разному можно
Например можно использовать RAII как предложили выше.

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

DrOffset,
Если что, я тебя не преследую))
Видимо некоторые темы интересны для нас обоих))
1
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
20.11.2018, 13:33
Цитата Сообщение от BaredJJ Посмотреть сообщение
cannot open file 'msvcprtd.lib' 1
В целом эта ошибка вообще не относится к С++, а говорит о том, что у вас что-то не так с настройками вашей среды компиляции. SDK не установлен или еще что.
1
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
20.11.2018, 13:35  [ТС]
Спасибо. Мне тоже эта тема показалась довольно интересной и весьма меня удивила, когда я это прочитал. Много вещей о которых не задумываешься в языках с управляемой сборкой мусора)
0
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
20.11.2018, 13:37
Цитата Сообщение от Undisputed Посмотреть сообщение
Просто помните что деструктор в случае исключения не будет вызван и учитывайте это.
А еще нужно помнить, то если неделегирующий конструктор отработал нормально, а делегирующий выбросил исключение, то деструктор будет вызван.
1
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
20.11.2018, 13:43  [ТС]
Цитата Сообщение от Croessmah Посмотреть сообщение
А еще нужно помнить, то если неделегирующий конструктор отработал нормально, а делегирующий выбросил исключение, то деструктор будет вызван.
То есть, если есть базовый класс и класс потомок, то при возникновении исключения в конструкторе класса потомка деструктор отработает? Или как то иначе?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
20.11.2018, 13:43
Цитата Сообщение от BaredJJ Посмотреть сообщение
Так правильней?
"Правильней" тут не может быть просто так. Я же вас спросил - "вам это зачем?". Это не значит, что вы сейчас же должны бросаться переделывать "как правильней", это значит, что вы должны подумать, зачем вы используете инструмент и ответить, в первую очередь себе. исходя из этого можно формулировать вопросы.

Цитата Сообщение от Undisputed Посмотреть сообщение
DrOffset,
Если что, я тебя не преследую))
Видимо некоторые темы интересны для нас обоих))
Я зашел в первую попавшуюся сверху
0
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
20.11.2018, 13:45  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
зачем вы используете инструмент и ответить, в первую очередь себе
Надо значит прокачаться в плюсах и минусах данных подходах.)
0
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
20.11.2018, 14:24
Цитата Сообщение от BaredJJ Посмотреть сообщение
То есть, если есть базовый класс и класс потомок, то при возникновении исключения в конструкторе класса потомка деструктор отработает?
Деструкторы созданных подъобъектов - да.
Деструктор класса, конструктор которого выбросил исключение - нет (если это не тот случай, о котором я написал выше).

Я же говорю о делегирующих конструкторах в одном классе.

Общий принцип такой - если объект создан, то для него вызывается деструктор при уничтожении.
Объект класса будет считаться созданным, если конструктор класса нормально завершится.
После выполнения неделегирующего конструктора объект уже создан, и если затем делегирующий конструктор выбросит исключение, то будет вызван деструктор для созданного объекта.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <stdexcept>
 
 
struct Some
{
    Some() { //неделегирующий конструктор
        std::cout << "Some::Some()" << std::endl;
    } 
    Some(int) { //неделегирующий конструктор, который выбросит исключение
        std::cout << "Some::Some(int)" << std::endl;
        throw std::logic_error("");
    } 
    
    Some(int, int): Some() { //делегирующий конструктор (делегирует создание объекта конструктору по-умолчанию)
        std::cout << "Some::Some(int, int)" << std::endl;
        throw std::logic_error("");
    } 
    
    ~Some() { 
        std::cout << "Some::~Some()" << std::endl;
    }
};
 
 
int main()
{
    try {
        Some x(10);//Для этого не будет вызван деструктор.
        //Some x(10, 10);//А для этого будет.
    } catch (...) {
        std::cout << "exception" << std::endl;
    }
}
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
20.11.2018, 14:24
Помогаю со студенческими работами здесь

Освобождение памяти при работе с DataTable
Работаю с большими таблицами (DataTable) локально. Есть ли какие-нибудь средства принудительного освобождения оперативной памяти? ...

Освобождение памяти при очистке ContentControl
Добрый день! Ситуация следующая, динамически создаю некотрый userControl, помещаю его в ContentControl. Далее (допустим при нажатии...

Освобождение памяти при выходе из программы
Просматривая исходные тексты программ, заметил, что часто на событие FormDestroy вешают удаление созданных компонентов (с помощью...

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

Освобождение памяти при вставке в QMap
Есть Qmap&lt;int,int*&gt; data; делаю инсерт int * d = new int; *d = 5; data.insert(0,d); d = new int; *d = 6; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru