указатели — C ++, выделение пространства в цикле for, возможная проверка утечки памяти

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

Node *newNode;

for (int i = 0; i < 10; i++)
{
newNode = new Node();
}

delete newNode;

Очевидно, что код ничего не делает, но он помогает мне объяснить мой сценарий. Я выделяю память 10 раз, и когда я удаляю указатель, оставляя 9 сирот? Или я повторно использую то же место, которое было выделено, и правильно удаляю сироту?
Заранее спасибо!

4

Решение

Да, это утечка памяти. Когда вы делаете:

newNode = new Node();

Вы переопределяете указатель так, чтобы он указывал на вновь выделенную память, фактически теряя способ адресации ранее указанной памяти для ее удаления.

Поэтому, когда вы выходите из цикла, newNode указатель указывает на последнюю (десятую) память /Node, Когда ты delete newNode Вы удаляете только эту память. У вас больше нет способа, которым delete другие.

Как Чжи Ван указал, что вы можете использовать некоторую форму умного указателя (unique_ptr или же shared_ptr в C ++ 11 например). Эти интеллектуальные указатели в основном являются обертками вокруг обычных указателей, которые имеют дополнительную семантику, предотвращающую этот вид утечек. Если вы используете один из них, память / объекты будут автоматически освобождены, когда они выйдут из области видимости (по окончании текущей итерации for цикл в этом случае).

тем не мение, Я не думаю, что это решит вашу ситуацию в этом случае. Я сомневаюсь, что вы хотите delete 10 объектов, как только вы их создадите. Скорее, вы, вероятно, хотите хранить эти объекты в контейнере, как std::vector или, по крайней мере, иметь массив указателей, указывающих на каждый из этих выделенных экземпляров. Таким образом, вы будете иметь объекты вокруг (что, я считаю, то, что вы хотите, так как вы создаете их вообще), а также способ удалить их позже.

6

Другие решения

Да, ваш код утечки памяти. Ваше первое предположение о поведении правильное. Этот код

Node *newNode;

for (int i = 0; i < 10; i++)
{
newNode = new Node();  // allocate memory 10 times in a loop...
}

delete newNode;            // ... but free the memory only once!

выделяет память 10 раз ( new оператор внутри for цикл), но освобождает память, используемую только один из этих объектов ( delete оператор внизу). Естественно, это оставляет остальные 9 объектов сиротами — память, которую они потребляют, по-прежнему выделяется, но теперь у вас нет возможности получить к ней доступ, чтобы освободить ее. Это, конечно, само определение утечки памяти.

В отличие от этого кода

Node *newNode;

for (int i = 0; i < 10; i++)
{
newNode = new Node();    // allocate memory 10 times in a loop
delete newNode;          // ... and free the memory each time
}

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

Или, может быть, даже лучше, когда вы работаете в C ++, никогда не используйте сырые указатели. Стандартная библиотека C ++ предоставляет несколько отличных классов-обёрток, которые реализуют идиому RAII для указателей, что гарантирует правильное уничтожение указанных объектов и, следовательно, освобождение используемой ими памяти. Начните свое исследование либо в вашем любимая книга C ++, или на Википедия.

3

По вопросам рекламы [email protected]