Почему эта программа на C ++ вызывает утечку памяти? - PullRequest
5 голосов
/ 11 февраля 2011

Рассмотрим следующий фрагмент кода:

char* str1 = new char [30];    
char* str2 = new char [40];   

strcpy(str1, "Memory leak");    
str2 = str1;     

delete [] str2;     
delete [] str1; 

Почему вышеуказанная программа вызывает утечку памяти? Как мне избежать этого?

Ответы [ 5 ]

21 голосов
/ 11 февраля 2011

Вышеуказанное не просто приводит к утечке памяти; это вызывает неопределенное поведение , что намного, намного хуже.

Проблема в трех последних строках:

str2 = str1; 
delete [] str2; 
delete [] str1; 

Если мы игнорируем эту первую строку, то последние две строки правильно восстанавливают всю память, выделенную в этой функции. Однако в этой первой строке str2 указывает на тот же буфер, что и str1. Поскольку str2 является единственным указателем в программе на динамическую память, на которую она ссылается, эта строка пропускает память для этого буфера. Хуже того, когда вы затем выполняете следующие две строки для очистки двух указателей, вы удаляете один и тот же блок памяти дважды, один раз через str2 и один раз до str1. Это приводит к неопределенному поведению и часто вызывает сбои. Особо злонамеренные пользователи могут фактически использовать это для выполнения произвольного кода в вашей программе, поэтому будьте осторожны, чтобы не делать этого!

Но здесь нужно учитывать одну проблему более высокого уровня. Вся проблема с этой настройкой состоит в том, что вы должны делать все свое собственное управление памятью. Если вы решите использовать std::string вместо необработанных строк в стиле C, то вы можете написать код следующим образом:

string str1 = "Memory leak"; // Actually, it doesn't. :-)
string str2;

str2 = str1; // Okay, make str2 a copy of str1

// All memory reclaimed when this function or block ends

Теперь нет необходимости явно управлять памятью, и вам не нужно беспокоиться о переполнении буфера или двойном освобождении. Вы спасены волшебством выделения памяти объекта.

20 голосов
/ 11 февраля 2011

Поскольку вы удаляете str1 (память, на которую он указывает) дважды, и вы не удаляете память, выделенную в том месте, на которое str2 впервые указывал.

EDIT: Я не уверен, чего вы пытаетесь достичь.

char* str1 = new char [30];
// str1 = 0x00c06810; (i.e.)
char* str2 = new char [40];
// str2 = 0x00d12340; (i.e.)
strcpy(str1, "Memory leak");

// delete [] str2; should be here

str2 = str1; 
// now str2 == str1, so str2 = 0x00c06810 and str1 = 0x00c06810
// deleting 0x00c06810
delete [] str2; 
// deleting 0x00c06810 once again
delete [] str1;
// 0x00d12340 not deleted - memory leak

Если вы хотите это назначение (str2 = str1), то сначала удалите str2.

4 голосов
/ 11 февраля 2011

Вы присваиваете указатель str1 указателю str2, поэтому delete [] str1 и delete [] str2 освобождают только память, указанную str1 (str2 указывает на ту же память). Вам нужно освободить память str2 перед тем, как потерять указатель на нее (перед назначением str1 для str2)

Правильный путь

char* str1 = new char [30];

char* str2 = new char [40]; //or just don't allocate this if You don;t need it

strcpy(str1, "Memory leak");

**delete [] str2;** 

str2 = str1; 


delete [] str1; 
2 голосов
/ 11 февраля 2011

делает указатели постоянными указателями

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

0 голосов
/ 11 февраля 2011

Каждый объект должен быть указан в памяти.

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

Таким образом, в вашем случае вы теряете место второго массиваобъем памяти.Итак, где-то в памяти потерян массив, к которому вы не можете добраться.

Когда вы делаете str2 = str1;, str2 указывает теперь на блок памяти, на который указывает str1.Так что на втором массиве ничего не осталось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...