Форум программистов, компьютерный форум CyberForum.ru

Есть ли утечка памяти в этом случае? - C++

Восстановить пароль Регистрация
 
 
NonCFist
0 / 0 / 0
Регистрация: 01.06.2013
Сообщений: 12
01.06.2013, 19:20     Есть ли утечка памяти в этом случае? #1
_Доброго денёчка всем. Прохожу тему на указатели и ссылки. Делаю упражнение на тему "написать программу, вызывающую утечку памяти". Смысл идеи "учись на ошибках и запомни как делать не нуна, а то будет ай-ай-ай".
В книге приведён пример такой логической ошибки, когда в функции выполняется создание экземпляра класса, для которого оператором new в функции выделяется память. Затем ссылка на объект передаётся в main для дальнейших издевательств..
_Ну вот я нечто в этом роде и написал. А потом малость подправил, и теперь не уверен, что в моем коде есть утечка памяти. Помогите, корифеи, Христа ради.

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
 // Логическая ошибка, приводящая к утечке памяти.
#include <iostream>
using namespace std;
 
class Detail
{
public: Detail (int length, int width);
        ~Detail ();
        int GetLength() const { return itsLength; }
        int GetWidth() const { return itsWidth; }
        void SetLength (int length) { itsLength = length; }
        void SetWidth (int width) { itsWidth = width; }
private:
    int itsLength;
    int itsWidth;
};
 
Detail::Detail (int length, int width)
{
    cout << " Calling constructor...\n";
    itsLength = length;
    itsWidth = width;
}
 
Detail::~Detail()
{
    cout << " Calling destructor...\n";
}
 
Detail & MakeDetail ();
 
int main()
{
    cout << "\n\n";
    Detail Det1(600, 510);
    cout << " Det.1 Length: " << Det1.GetLength() << " mm.\n";
    cout << " Det.1 Width: " << Det1.GetWidth() << " mm.\n";
    cout << "\n";
    Detail Det2 = MakeDetail();  
    cout << " Det.2 Length: " << Det2.GetLength() << " mm.\n";
    cout << " Det.2 Width: " << Det2.GetWidth() << " mm.\n";
    cout << "\n\n";
    system ("pause");
    return 0;
}
 
Detail & MakeDetail ()
{
    cout << " Calling MakeDetail...\n";
    Detail * NewDetail = new Detail (0, 0);
    NewDetail->SetLength(704);
    NewDetail->SetWidth(510);
    return *NewDetail;
}
Output:

Calling constructor...
Det.1 Length: 600 mm.
Det.1 Width: 510 mm.

Calling MakeDetail...
Calling constructor...
Det.2 Length: 704 mm.
Det.2 Width: 510 mm.


Для продолжения нажмите любую клавишу . . .
Caling destructor...
Caling destructor...

Деструктор, как видите, вызывается дважды. Или таки память от *NewDetail не очищена?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.06.2013, 19:20     Есть ли утечка памяти в этом случае?
Посмотрите здесь:

Утечка памяти C++
Утечка памяти?! C++
C++ Утечка памяти
Есть ли утечка памяти? C++
Утечка памяти C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
02.06.2013, 14:50     Есть ли утечка памяти в этом случае?
  #21

Не по теме:

Цитата Сообщение от IGPIGP Посмотреть сообщение
А я согласен с alex_x_x в том, что ссылка на локально созданный, динамический объект не обязательно не валидна.
что-то не найду где сказано обратное
Цитата Сообщение от IGPIGP Посмотреть сообщение
Классический пример возврата ссылки на локальную переменную:
Классический пример оШЫбки

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6171 / 2900 / 283
Регистрация: 04.12.2011
Сообщений: 7,710
Записей в блоге: 3
02.06.2013, 15:34     Есть ли утечка памяти в этом случае? #22
Цитата Сообщение от Jupiter Посмотреть сообщение
Классический пример оШЫбки
Это и имеется ввиду. И по тексту комментария и в последней фразе:
Цитата Сообщение от IGPIGP Посмотреть сообщение
как в самом первом случае, где всё предельно ясно: локальная переменная - ссылка - кирдык
Цитата Сообщение от Jupiter Посмотреть сообщение
что-то не найду где сказано обратное
Да в топике же. Ведь если ссылка валидна, то нет утечки. Создаем указатель, присваиваем адрес ссылки, удаляем с помощью delete (понятно, - плохая практика, разные области видимости, чревато ошибками при невнимательности...), но утечки в этом случае, строго говоря нет, так как возможность освободить память не утрачена. Это же не случай:
C++
1
2
3
4
int a=123;
int *p1=&a;
int *p2=new int[123];
p2=p1;//память выделенная под массив потеряна
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
07.06.2013, 14:16     Есть ли утечка памяти в этом случае? #23
IGPIGP, так там же другой случай. Код ТСа равносилен следующему:
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
// Теперь возвращаем указатель
Detail *MakeDetail ()
{
    cout << " Calling MakeDetail...\n";
    Detail * NewDetail = new Detail (0, 0);
    NewDetail->SetLength(704);
    NewDetail->SetWidth(510);
    // Теперь без разыменования
    return NewDetail;
}
 
int main()
{
    cout << "\n\n";
    Detail Det1(600, 510);
    cout << " Det.1 Length: " << Det1.GetLength() << " mm.\n";
    cout << " Det.1 Width: " << Det1.GetWidth() << " mm.\n";
    cout << "\n";
    // Теперь разыменовываем указатель на динамическую память
    Detail Det2 = *MakeDetail();
    // А теперь потеряли указатель... память утекла
    cout << " Det.2 Length: " << Det2.GetLength() << " mm.\n";
    cout << " Det.2 Width: " << Det2.GetWidth() << " mm.\n";
    cout << "\n\n";
    system ("pause");
    return 0;
}
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6171 / 2900 / 283
Регистрация: 04.12.2011
Сообщений: 7,710
Записей в блоге: 3
07.06.2013, 17:53     Есть ли утечка памяти в этом случае? #24
delete - не всмотрелся в Ваш пример, - теперь понял, но:
В примере речь именно о ссылке на безымянную динамическую переменную. Создаётся она локально как и указатель, но живёт долго. По моим наблюдениям столько же, сколько и динамический объект(?). Тут нет уверенности.

Добавлено через 1 час 6 минут
silent_1991, Ваш пример не похож на вопрос темы. В нём возвращаемый безымянный указатель разыменовывается и значение коприруется в новую созданную переменную (при присваивании или при инициализации не важно). Когда результат принимает ссылка то и в Bашем примере, разыменование указателя во внешней области видимости предоставляет ссылку на динамический объект:
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
#include <iostream>
using namespace std;
class Detail{
int len;
int wid;
public:
    Detail(int _len=0, int _wid=0):len(_len), wid(_wid){}
    Detail(Detail& a):len(a.len), wid(a.wid){cout<<"copyConstr !!!"<<endl;}
void SetLength(int a){len=a;}
void SetWidth(int a){wid=a;}
int GetLength(){return len;}
int GetWidth(){return wid;}
};
Detail *MakeDetail ()
{
    cout << " Calling MakeDetail...\n";
    Detail * NewDetail = new Detail (0, 0);
cout << " Pointer in MakeDetail... "<<NewDetail<<endl;
    NewDetail->SetLength(704);
    NewDetail->SetWidth(510);
    // Теперь без разыменования
    return NewDetail;
}
int main()
{setlocale(0,"rus");
    cout << "\n\n";
    Detail Det1(600, 510);
    cout << " Det.1 Length: " << Det1.GetLength() << " mm.\n";
    cout << " Det.1 Width: " << Det1.GetWidth() << " mm.\n";
    cout << "\n";
    // Теперь разыменовываем указатель на динамическую память
    Detail Det2 = *MakeDetail();
    cout << " Adress out of MakeDetail by copy... "<<&Det2<<" that is a fleak"<<endl;
    // А теперь потеряли указатель... память утекла
    cout << " Det.2 Length: " << Det2.GetLength() << " mm.\n";
    cout << " Det.2 Width: " << Det2.GetWidth() << " mm.\n";
    cout << "\n\n";
    //это прмнмсающая ссылка, она не копирует всебя так как не создаётся в ввиде 
    //самостоятельной переменной как в Вашем примере и коструктор копий не будет вызван
    Detail& Det3 = *MakeDetail();
    cout << " Adress out of MakeDetail by ref... "<<&Det3<<" that is not a fleak"<<endl;
    // А теперь потеряли указатель?... память утекла?
    cout << " Det.3 Length: " << Det3.GetLength() << " mm.\n";
    cout << " Det.3 Width: " << Det3.GetWidth() << " mm.\n";
    cout << "\n\n";
    //а теперь Горбатый:
    delete &Det3;
    cout << " And finnaly uncoment following two lines to have a bit of garbage... "<<endl;
    //cout << " Det.3 Length: " << Det3.GetLength() << " mm.\n";
    //cout << " Det.3 Width: " << Det3.GetWidth() << " mm.\n";
    cout << "\n\n";
    system ("pause");
    return 0;
}
Напоследок в качестве шутки, фрагмент (утрированный мной) увиденный в вопросе одного гостя:
C++
1
2
3
4
5
6
void foo(){
//-------------------------------
int *P = ( new int[10]!=0 )? new int[10] : 0;
//-------------------------------
}
:D
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
07.06.2013, 18:21     Есть ли утечка памяти в этом случае? #25
Цитата Сообщение от IGPIGP Посмотреть сообщение
//это прмнмсающая ссылка, она не копирует всебя так как не создаётся в ввиде
* * //самостоятельной переменной как в Вашем примере и коструктор копий не будет вызван
Дык в коде ТСа было не так:
C++
1
Detail& Det3 = MakeDetail();
а так:
C++
1
Detail Det3 = MakeDetail();
И память здесь утекает, потому что сразу после копирования память остаётся висеть без привязки к каким-либо указателям или ссылкам. Или я опять чего-то не понял и не на то отвечаю?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11836 / 6815 / 770
Регистрация: 27.09.2012
Сообщений: 16,898
Записей в блоге: 2
Завершенные тесты: 1
07.06.2013, 18:31     Есть ли утечка памяти в этом случае? #26
silent_1991, Всё верно

Добавлено через 2 минуты
И вопрос с ссылкой был рассмотрен еще в первых постах и ТС сам же написал, что убрал амперсанд потому что не понял зачем он там нужен
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6171 / 2900 / 283
Регистрация: 04.12.2011
Сообщений: 7,710
Записей в блоге: 3
07.06.2013, 18:38     Есть ли утечка памяти в этом случае? #27
silent_1991, меня смутил вот этот пост:
Есть ли утечка памяти в этом случае?
то есть я понял так, что [ТС] не дал код оригинала, где было:
C++
1
Detail& Det2 = MakeDetail();
и привел код в виде:
C++
1
Detail Det2 = MakeDetail();
В противном случае, всё что я написал, - не к месту.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11836 / 6815 / 770
Регистрация: 27.09.2012
Сообщений: 16,898
Записей в блоге: 2
Завершенные тесты: 1
07.06.2013, 18:43     Есть ли утечка памяти в этом случае? #28
IGPIGP, Посты #6 и #14
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.06.2013, 18:54     Есть ли утечка памяти в этом случае?
Еще ссылки по теме:

C++ утечка памяти
C++ Утечка памяти
Есть ли утечка памяти в list C++

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

Или воспользуйтесь поиском по форуму:
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6171 / 2900 / 283
Регистрация: 04.12.2011
Сообщений: 7,710
Записей в блоге: 3
07.06.2013, 18:54     Есть ли утечка памяти в этом случае? #29
Цитата Сообщение от Croessmah Посмотреть сообщение
IGPIGP, Посты #6 и #14
Так из них то всё ясно конечно, и всем. Но поcле #6 [ТС] пишет далее:
Есть ли утечка памяти в этом случае?
И это не вселяет уверенности. Я например, засомневался.
Yandex
Объявления
07.06.2013, 18:54     Есть ли утечка памяти в этом случае?
Ответ Создать тему
Опции темы

Текущее время: 23:49. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru