Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
5 / 5 / 0
Регистрация: 28.11.2010
Сообщений: 81
1

Чтобы не было утечек памяти

10.11.2011, 22:15. Просмотров 1111. Ответов 15
Метки нет (Все метки)

Товарищи, такой вопрос:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class node
{
int *a;
double *b;
vector<node *> vec;
public:
//тут методы
}
 
node::~node()
{
delete a;
delete b;
}
Все ли необходимое я очистил в деструкторе? С вектором что-нибудь надо делать?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.11.2011, 22:15
Ответы с готовыми решениями:

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

Подключении механизма обнаружение утечек памяти
// output N number of M devide L.cpp : Defines the entry point for the console application. // ...

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

Visual Studio 2015 Обнаружение утечек памяти
В 13 студии в окно лога отладчика выводилось сообщение. Вася забыл про оператор delete! Detected...

15
Эксперт С++
623 / 467 / 57
Регистрация: 28.01.2011
Сообщений: 605
10.11.2011, 22:19 2
Svinina, каждый элемент в векторе тоже должен быть освобождён вручную, delete для них при разрушении вектора не вызывается.
0
Каратель
Эксперт С++
6596 / 4017 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
10.11.2011, 22:19 3
Цитата Сообщение от Svinina Посмотреть сообщение
Все ли необходимое я очистил в деструкторе? С вектором что-нибудь надо делать?
мало данных
0
24 / 24 / 0
Регистрация: 08.09.2010
Сообщений: 136
10.11.2011, 22:21 4
Да, надо. Пробегитесь по вектору и поделяйте все элементы (если сами они не нужны после удаления объекта) а потом:
C++
1
vec.clear();
0
113 / 113 / 13
Регистрация: 29.04.2010
Сообщений: 240
10.11.2011, 22:24 5
Я бы еще проверял указатель на null, прежде чем удалять.
0
Каратель
Эксперт С++
6596 / 4017 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
10.11.2011, 22:25 6
Цитата Сообщение от PraZuBeR Посмотреть сообщение
Я бы еще проверял указатель на null, прежде чем удалять.
зачем? delete можно применять к указателю на null
1
5 / 5 / 0
Регистрация: 28.11.2010
Сообщений: 81
10.11.2011, 22:34  [ТС] 7
Ну если мало, то так:

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
class node
{
    int *a;
    double *b;
    vector<node *> vec;
public:
    node();
    node(node *n, node *m);
    ~node();
}
 
node::node()
{
    a = new int(1);
    b = new double(2.0);
}
node::node(node *n, node *m)
{
    a = new int(1);
    b = new double(2.0);
    vec.push_back(n);
    vec.push_back(m);
}
 
node::~node()
{
    delete a;
    delete b;
}
Добавлено через 3 минуты
Цитата Сообщение от DKOI Посмотреть сообщение
Да, надо. Пробегитесь по вектору и поделяйте все элементы (если сами они не нужны после удаления объекта) а потом:
C++
1
vec.clear();
В этом случае вызывается деструктор вектора?
И что вы имеете ввиду под "поделяйте все элементы"? Ерейзом из вектора их повыкидывать, или поубивать объекты, на которые ссылаются элементы этого вектора?
0
Заблокирован
10.11.2011, 22:37 8
имхо, в векторе над держать либо сами объекты, и тогда простого vec.clear() будит достаточно

либо держать интеллектуальные указатели на эти объекты, и тогда простого vec.clear() будит достаточно.

/ps вектор интеллектуальных указателей поганит память так же, как лист объектов.
Но работает медленнее, чем лист.
0
24 / 24 / 0
Регистрация: 08.09.2010
Сообщений: 136
10.11.2011, 22:57 9
Цитата Сообщение от Svinina Посмотреть сообщение
И что вы имеете ввиду под "поделяйте все элементы"? Ерейзом из вектора их повыкидывать, или поубивать объекты, на которые ссылаются элементы этого вектора?
Поделять - сделать delete для каждой ссылки хранящейся в векторе. Иначе бы я сказал выкинуть Да и вообще, если еразить все елементы, зачем clear бы тогда вызвать?
0
5 / 5 / 0
Регистрация: 28.11.2010
Сообщений: 81
10.11.2011, 23:07  [ТС] 10
Цитата Сообщение от DKOI Посмотреть сообщение
Поделять - сделать delete для каждой ссылки хранящейся в векторе. Иначе бы я сказал выкинуть Да и вообще, если еразить все елементы, зачем clear бы тогда вызвать?
Ну а если, скажем, мэйн имеет вид:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
 
node *a = new node;
node *b = new node;
node *c = new node(&a, &b);
 
//....
 
delete c;
 
//тут c больше нигде не используется, а a и b используются
 
delete a;
delete b;
 
return 0;
}
Тут будет утечка, если использовать деструктор вида:
C++
1
2
3
4
5
node::~node()
{
    delete a;
    delete b;
}
?

просто если прописать delete в деструкторе для элементов вектора, я объектами a и b же после удаления с пользоваться не смогу?
0
Заблокирован
10.11.2011, 23:39 11
Здесь налицо архитектурная ошибка.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main()
{
node *a = new node;
node *b = new node;
node *c = new node(&a, &b);  //кто владелец данных?
//....
delete c;  //мы можем убить любой объект. 
              //А объект в этот момент может держать
              // указатели на другие себеподобные объекты.
              // Может получится ситуация, когда объект 
              //будит держать ссылки на уже убитые объекты. 
              //Это может привести к печальным последствиям.
 
//тут c больше нигде не используется, а a и b используются
delete a;  //А если объект с считает себя владельцем 
               //собственных данных, и попытается сделать 
               //им delete в своём диструкторе? 
               //Не получится двойного delete одному 
               //участку памяти?
delete b;
return 0;
}
Нарушение инкапсуляции. Класс не в состоянии обеспечить безопасность собственных данных.

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

1. разработчик класса не установил четких правил владения данными. Не понятно, кто является владельцем данных - указатели извне класса, или указатели изнутри класса?

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

3. Если владелец данных - класс, то наружная сторона не должна никаким образом иметь указатели на внутренние данные класса.

Иначе, считай , что уже имеем нарушение инкапсуляции: данные ничем никак не защищены, а наружная сторона сможет сделать с ними все что угодно. Например сделать им delete.
0
5 / 5 / 0
Регистрация: 28.11.2010
Сообщений: 81
10.11.2011, 23:50  [ТС] 12
Bers, так что, получается вообще нельзя использовать указатели на класс внутри этого класса? Ведь в общем случае указанные тобой проблемы возникнут в любом случае и никак от них не избавиться?
0
Заблокирован
10.11.2011, 23:58 13
Цитата Сообщение от Svinina Посмотреть сообщение
Bers, так что, получается вообще нельзя использовать указатели на класс внутри этого класса? Ведь в общем случае указанные тобой проблемы возникнут в любом случае и никак от них не избавиться?
Это же с++, можно все. И исправить в большинстве случаев тоже всегда все можно)

Вам нужно определиться: кто за какие данные отвечает. В первую очередь.

Например: "класс может хранить указатели на себе подобные объекты, но не является их владельцем. Поэтому, он не будит освобождать данные по этим указателям".

В этом случае, в диструкторе класса вектор класса только тупо делает clear() и больше ничего.

Или так: "Класс принимает право владения объектом, на который указывает пришедший к нему указатель". В этом случае, класс запоминает где лежит объект, а пришедший указатель обнуляет. Теперь у вызывающей стороны будет нулевой указатель. Она ничего не сможет с ним сделать. А класс, принявший право владения объектом должен будит отвечать за корректное уничтожение этого объекта (пробежать по всему вектору, и сделать delete каждому элементу)

Короче говоря, сделать можно как угодно. Можно вообще через интеллектуальные указатели замутить. Зависит от задачи, и от самого программиста. Главное - что бы было четкое разделение ответственности и прав владения между классом и вызывающей стороной.
1
5 / 5 / 0
Регистрация: 28.11.2010
Сообщений: 81
11.11.2011, 00:08  [ТС] 14
Например: "класс может хранить указатели на себе подобные объекты, но не является их владельцем. Поэтому, он не будит освобождать данные по этим указателям".

В этом случае, в диструкторе класса вектор класса только тупо делает clear() и больше ничего.
А как в таком случае победить это?
C++
1
2
3
4
5
6
delete c;  //мы можем убить любой объект. 
              //А объект в этот момент может держать
              // указатели на другие себеподобные объекты.
              // Может получится ситуация, когда объект 
              //будит держать ссылки на уже убитые объекты. 
              //Это может привести к печальным последствиям.
И еще, если clear в деструкторе не выполнить, указатели лежащие в нем так и будут в памяти болтаться образуя утечку?
0
Заблокирован
11.11.2011, 00:31 15
Цитата Сообщение от Svinina Посмотреть сообщение
А как в таком случае победить это?
Это правильный вопрос. Если класс не является владельцем объектов, значит он не контролирует время жизни этих объектов.

Но он хранит указатели на них не просто так, а для того, что бы иметь возможность обратиться через них к этим объектам.
И поэтому, ему очень важно иметь возможность узнать - а эти объекты вообще ещё живы?

Как это можно сделать? Способов много. Опять таки, зависит от конкретной задачи.
Один из способов - использовать не обычные указатели, а "интеллектуальные" указатели.
Что это такое, как они работают, и как их можно применять - узнайте у гугла.
Если будит потом ещё что-то непонятно - спрашивайте.

Но лично я стараюсь по возможности не прибегать к услугам интеллектуальных указателей.
Я бы скорее всего использовал что то вроде вот такого алгоритма:

1. При создании объекта, он получает знание о том, где лежит его "регистрационный массив данных". И тут же, при создании, он регистрирует свой собственный указатель в этом регистрационном массиве.

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

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

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

5. Если по задаче "регистрационный массив" должен быть только один на все объекты класса, то можно сделать его "статическим данным-членом" (см "статические данные-члены класса").


Цитата Сообщение от Svinina Посмотреть сообщение
И еще, если clear в деструкторе не выполнить, указатели лежащие в нем так и будут в памяти болтаться образуя утечку?
Когда вы делаете вектору метод clear() то, вектор полностью освобождает свою память.
То есть, он вызывает диструкторы всем элементам, которые содержит, а потом полностью удаляет память, которую эти элементы занимали.

Если вектор содержит только указатели - то память, которую занимали эти указатели будит освобождена. Но! Освобождена будит память, которую занимали сами указатели. А память, на которую указывали эти указатели так и останется неосвобождённой.


Добавлено через 1 минуту
Цитата Сообщение от Svinina Посмотреть сообщение
И еще, если clear в деструкторе не выполнить, указатели лежащие в нем так и будут в памяти болтаться образуя утечку?
Вообще, когда у объекта-хозяина закончится время жизни, то будут автоматически разрушены все его данные-члены, созданные на стеке. Для них автоматически будут вызваны ихние диструкторы.

У вектора диструктор вызывает метод clear() Таким образом, при разрушении, вектор сам автоматически чистит за собой.
1
5 / 5 / 0
Регистрация: 28.11.2010
Сообщений: 81
11.11.2011, 00:38  [ТС] 16
Bers, спасибо большое, в общем то все по полочкам разложил.=)
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.11.2011, 00:38

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

Подскажите программу для диагностики утечек памяти
Здравствуйте. В одном блоге почитал, что диспетчер задач для диагностики утечек не предназначен....

Если применять эту функцию к массиву, то он будет удаляться без всяких утечек памяти и т.п.?
//Функция удаления двумерного массива void delete_array(int** arr, int row) { for (int i = 0; i...

Устал от утечек памяти
С этими утечками памяти в C++ просто беда. Посоветуйте, что можно сделать? Может быть есть какие-то...

Как отписаться от события чтобы не было утечки памяти
Здравствуйте, подскажите как отписаться от события чтобы не было утечки памяти. Все равно после...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.