2015-10-08 2 views
-2

В настоящее время я ударяю головой о школьное задание и имею дело с довольно неприятными утечками памяти. Во время отладки я сузил часть проблемы до одного фрагмента кода.Почему этот код создает утечку памяти?

Вот чрезвычайно упрощенная версия того кода, который я переделан, чтобы проиллюстрировать утечку:

_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); 
    _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); 
    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); 
    _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT); 
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); 
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT); 

    do { 
     char *name = new char; 
     char *cname = new char[10]; 
     cin >> cname; 

     name = cname; 
     delete [] name; 

    } while(false); 

    _CrtDumpMemoryLeaks(); 

Так что мой вопрос, почему это производит утечку памяти? Я пробовал кучу вещей, чтобы исправить это, но ничего не работает.

EDIT:

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

Простые вопросы получают простые ответы. Спасибо.

+0

'символ * имя = nullptr' будет указывать без памяти, но вызов' new' выделяет память (и, следовательно, должно быть высвобождено) – Tas

+0

Вы выделяете char, выделите 10 символов, сделайте что-нибудь, удалите 10 символов, но никогда не удаляйте один символ (который вам фактически не нужно выделять, но вы это сделали). – immibis

ответ

2

Вы вызываете новое дважды, но только один раз удаляете.

+0

, но хуже, он перезаписывает одно из своих распределений, которое впоследствии не может быть удалено, и первое выделение даже не требуется – Les

0

Очевидно, что вы не пытались удалить name - первый char вы выделяете перед сбросом name на что-то еще, и потерять все ссылки на начальном этапе ...

+0

Downvoter, пожалуйста, объясните? – John3136

+0

+0.9, чтобы компенсировать downvote, потому что нет ничего плохого в этом сообщении – Tas

+1

@ Это было теневой попыткой обойти запрет на комментарии «+ один»? Если это так, вероятно, должно быть «+0.999 ...». Или «+ один» как другой вариант, очевидно :-) – paxdiablo

1

char* name = new char; вы

, но потом вам замените (забудьте) значение name с name = cname;

, чтобы исходный new char не был удален.

0

Просто следуйте код, чтобы увидеть то, что получает выделяется и освобождается:

char *name = new char;  // Block 1, name references it 
char *cname = new char[10]; // Block 2, cname references it 
: 
name = cname;    // name/cname now reference block 2 *** 
delete [] name;    // free up block 2 

Вы можете увидеть на *** линии, которую вы потерять указатель на блок 1, следовательно, ваша утечка памяти. Даже если у вас был код, который пытался освободить блок 1, у вас больше нет ссылки на него после этой точки.

Если вы собираетесь потерять весь доступ к блоку памяти, то лучше освободить его первый:

char *name = new char;  // Block 1, name references it 
char *cname = new char[10]; // Block 2, cname references it 
: 
delete name;     // free up block 1 
name = cname;    // name/cname now reference block 2 *** 
delete [] name;    // free up block 2 

Что касается Вашего комментария:

Для некоторых Причина была в предположении, что указатель, инициализированный без значения, указывает на NULL, а не на блок памяти, и поэтому его не нужно обрабатывать.

Что указатель инициализирован, если вы не укажете, что зависит от нескольких факторов. Тем не менее, это не имеет значения здесь, потому что вы сделать инициализировать его.Если вы хотите установить указатель на NULL, просто сделать это:

char *name = 0; // not "new char". 
Смежные вопросы