Утечка памяти при назначении нового значения переменной? - PullRequest
4 голосов
/ 08 августа 2011

Да, я один из тех, кто изучает C ++ из Java, будучи испорченным автоматическим сборщиком мусора.Есть особая ситуация, когда мне интересно, у меня утечка памяти или нет.Давайте рассмотрим в C ++:

bool *test = new bool(false);
test = new bool(true);
delete test;

Я теряю память здесь?Или я должен сначала позвонить delete перед назначением нового значения?Вот так:

bool *test = new bool(false);
delete test;
test = new bool(true);
delete test;

Мое чувство кишки говорит мне, что первое верно, так как указатель test указывает на тот же адрес в памяти, и присвоение нового значения его переменной не изменит этот адрес,Или оператор new выделяет другой адрес в памяти?Кто-нибудь может дать мне подсказку, или я все неправильно понял?

Ответы [ 7 ]

6 голосов
/ 08 августа 2011

Да, у вас есть утечка, и c ++ способ сделать это:

bool test = false;
test = true; 

// ta-da - no leak.

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

5 голосов
/ 08 августа 2011

Да, точно, вам нужно delete, прежде чем перезаписать адрес.Или еще лучше распределить по стеку или использовать умный указатель.

1 голос
/ 08 августа 2011

Вы действительно были испорчены.

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


bool *test = new bool(false);
  • Выделите пространство с автоматической продолжительностьюдля test
  • Выделение пространства с динамической продолжительностью для bool
  • Запись false в это пространство
  • Сохранение адреса этого пространства в test

test = new bool(true);
  • Выделить пространство с динамической продолжительностью для bool
  • Записать true в это пространство
  • Сохранить адрес этого пространства в test (ранее сохраненный адрес безжалостно отбрасывается, так как он больше нигде не хранится, память, на которую он указывает, никогда не может быть восстановлена, что означает, что у вас есть утечка).

delete test;
  • Считайте адрес, сохраненный в test
  • Распределите пространство по этому адресу

Мое чувство кишки говорит мне, что первое правильно,как указатель теста указывает на тот же адрес в памяти, и присваиваяновое значение для его переменной, не изменит этот адрес.Или новый оператор выделяет другой адрес в памяти?

Семантически, вы должны учитывать, что new всегда возвращает адрес в пространство new в памяти (очевидно, ложно, так как память используется повторно).Вот почему каждый вызов new должен совпадать с ровно одним вызовом delete.

Поэтому ваше внутреннее чувство неверно, new не создает "просто"Переменная.Если вы пришли из Java, это может быть действительно шокирующим, и вам понадобится сильное руководство, чтобы понять тонкости программирования.

0 голосов
/ 09 августа 2011

Да, у вас утечка памяти в первом случае.Второй способ - это правильный способ сделать это.В вашем первом случае ...

Когда вы вызываете new во второй раз, первое выделение выходит из области действия, но все еще существует.В Java это хорошо, потому что GC очистит его для вас.Однако в C ++ такого способа с необработанными спойнерами не существует.

Каждый вызов new также должен иметь вызов для удаления в определенный момент.Кроме того, после удаления указателя установите его на ноль или 0. Это предотвратит случайное удаление недействительной памяти.

0 голосов
/ 08 августа 2011

bool - это встроенный тип данных. Почему вам нужно выделять память таким образом? Вы можете легко выделить в стеке

0 голосов
/ 08 августа 2011

Да, ваш первый пример - утечка памяти. Каждый вызов new должен иметь соответствующий вызов delete (если new не удалось).

В C ++ обычный способ сделать то, что вы пытаетесь сделать, - это просто объявить bool локально:

bool b = truel
b = false;

Если, тем не менее, по какой-то причине вам действительно требуется динамическое выделение, существуют умные указатели, которые управляют памятью, поэтому вам не нужно беспокоиться о вызове delete. Вы можете посмотреть scoped_ptr, unique_ptr и shared_ptr.

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

Если вы серьезно относитесь к изучению C ++, я бы выбрал одну из книг в списке книг SO C ++ и изучил бы ее с нуля, а не пытался переносить идиомы Java в C ++ (это просто не будет работать хорошо).

0 голосов
/ 08 августа 2011

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

...