Как реализовано удаление и удаление []? - PullRequest
1 голос
/ 25 марта 2012

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

Два типа:

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

Я думаю, может утечка утечка.потому что функция разрушения.

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

Как реализованы delete и delete[]?

Ответы [ 4 ]

4 голосов
/ 25 марта 2012

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

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

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

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

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

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

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

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

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

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

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

4 голосов
/ 25 марта 2012

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

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

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

Краткий ответ: поскольку в спецификации так сказано.

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

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

1 голос
/ 25 марта 2012

Наваз прав, что это «потому что в спецификации так сказано».

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

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

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

0 голосов
/ 25 марта 2012

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

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

...