2012-03-25 5 views
1

Когда я использую new [] для применения памяти. В конце я использую delete для освобождения памяти (не delete[]). Это приведет к утечке памяти?Как удалить и удалить []?

Два типа:

  1. Builtin типы, как int, char, double ...
    Я не уверен.
  2. типы классов.

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

Многие люди и некоторые книги говорят мне, new[] ->delete[]; new ->delete.
Я хочу знать, почему. поэтому я проверяю исходный код vs2010, он должен использовать механизм пула памяти. Он длинный и сложный. Я не могу продолжать читать.

Как применяются delete и delete[]?

ответ

4

Когда я использую новый [] для применения памяти. В конце я использую delete для свободного memeory (не удалять []). Должна ли быть утечка памяти?

Если вы используете new[], а затем delete (не delete[]), то в соответствии со спецификацией LANGAUGE, она вызывает неопределенное поведение-что означает, что-то может случиться. Это может вызвать утечку памяти или не может. Никакая такая гарантия не предоставляется языком или компилятором.

Многие люди и некоторые книги рассказывают мне, новые [] -> delete []; новый-> удалить. Я хочу знать, почему?

Короткий ответ: потому что спецификация говорит так.

Длинный ответ: функции, которые реализуют new и new[] реализованы по-разному: new предполагает память одного элемента должен быть выделен, в то время как new[] предполагает память n элемента должна быть выделена где n передается функции в качестве аргумента. Таким образом, чтобы отменить процесс (то есть освободить память), должны быть также две функции: delete и delete[], которые реализованы по-разному, каждый из которых делает некоторые предположения о памяти, выделенной их коллегами. Например, delete просто предполагает, что память, выделенная для одного элемента, должна быть освобождена; с другой стороны, delete[] должен знать количество элементов, для которых память должна быть освобождена, поэтому предполагается, что new[] хранит номер элементов где-то в выделенной памяти, чаще всего в начале выделенной памяти, и поэтому delete[] сначала считывает ту часть памяти, которая хранит количество элементов, а затем освобождает память.

Обратите внимание, что new и new[] каждый вызывает конструктор по умолчанию, чтобы построить объект (ы) в выделенной памяти, а также delete и delete[] вызывает деструктор для уничтожения объекта перед освобождением памяти.

+0

хотя это правда, это не вопрос [I * think *] - он спрашивает о том, как это реализовано. [Я согласен, вопрос был не очень ясен, прежде чем я его редактировал ...] – amit

+0

Во-первых, спасибо. amit, прав. Я хочу знать, «как это реализовано?» –

+0

@chinazhangjie: Я думаю, что я кратко объяснил *, как каждый реализован. Вы хотите * актуальную * реализацию? – Nawaz

0

Вы не должны этого делать. Хотя для большинства реализаций вы можете безопасно удалить массив с удалением вместо delete [], , если тип элемента массива не имеет деструктора.

Для типа с деструктором новый [] должен будет записывать длину массива где-то в динамически выделенном блоке памяти. delete [] уничтожит каждую базовую базу, и, наконец, освободит блок памяти. И delete не распознает такую ​​структуру. Возможно, это утечка памяти, может быть, вы получите какое-то исключение.

4

Это не утечка памяти; это undefined поведение. Это намного хуже.

Вызов delete по памяти, выделенной new[], может привести к разложению кучи, что может привести к краху вашего приложения. Не сразу, конечно, потому что это было бы слишком полезно. Это может произойти когда-нибудь позже, спустя много времени после того, как куча была повреждена, что почти невозможно было отследить.

Всегда используйте delete[] с new[]. На самом деле, никогда не использовать new[] для начала. Используйте std::vector, если у вас нет особых и конкретных потребностей.

Я хочу знать почему?

Почему это имеет значение? Это неправильный и приводит к сломанной программе. Это неправильно, потому что стандарт C++ так говорит.

Однако, если вы настаиваете на причины ...

Обратите внимание, что вы можете выделить любое количество элементов с new[]. Вы можете поместить любой счетный номер (aka: positive integer). Таким образом, вы можете получить new int[50] или new int[someIntegerVariable]. Все хорошо.

Также обратите внимание, что delete[] делает не считать счет. Ну ... как это возможно? Если вы выделите 50 int с, очевидно, delete должен знать, сколько вы выделили, не так ли? Но вам не нужно это говорить; он автоматически знает.

Как? Потому что new int[50] выделяет больше, чем просто массив из 50 int s. Он также выделяет достаточно места для хранения размера выделения. Подумайте об этом как о распределении 51 int, но разрешите использовать только 50 из них.

Затем идет delete[]. Он определяет, где найти счет, выделенный new[]. И он использует этот счет для освобождения памяти.

deleteнет сделаю это. Поэтому он не может правильно освободить память.

1

Nawaz правильно, что это «потому что спецификация говорит так».

Причина реализации заключается в том, что при вызове delete компилятор добавляет вызов деструктору объекта перед освобождением памяти.

В случае массива количество вызовов деструкторов зависит от количества выделенных объектов, которое известно только во время выполнения. Таким образом, new[] сохраняет дополнительную информацию о количестве объектов, которые использует delete[].

Эта информация не требуется при использовании new/delete.