после обсуждения на соблюдении программного обеспечения я намеревался узнавать при удалении динамично выделенного, массива примитивов с плоскостью delete
вызовет утечку памяти.
Я записал эту крошечную программу и скомпилировал ее с Visual Studio 2008, работающий на Windows XP:
#include "stdafx.h"
#include "Windows.h"
const unsigned long BLOCK_SIZE = 1024*100000;
int _tmain()
{
for (unsigned int i =0; i < 1024*1000; i++)
{
int* p = new int[1024*100000];
for (int j =0;j<BLOCK_SIZE;j++) p[j]= j % 2;
Sleep(1000);
delete p;
}
}
Я, чем контролируемый потребление памяти моего приложения с помощью диспетчера задач, удивительно память была выделена и освобождена правильно, выделенная память постоянно не увеличивалась, как ожидался
Я изменил свою тестовую программу для выделения не массива типа примитива:
#include "stdafx.h"
#include "Windows.h"
struct aStruct
{
aStruct() : i(1), j(0) {}
int i;
char j;
} NonePrimitive;
const unsigned long BLOCK_SIZE = 1024*100000;
int _tmain()
{
for (unsigned int i =0; i < 1024*100000; i++)
{
aStruct* p = new aStruct[1024*100000];
Sleep(1000);
delete p;
}
}
после выполнения для в течение 10 минут не было никакого значимого увеличения памяти
Я скомпилировал проект с предупреждением уровня 4 и не получил предупреждений.
действительно ли возможно, что время выполнения Visual Studio отслеживает выделенные типы объектов, таким образом, там не отличается между delete
и delete[]
в той среде?
delete p, где p — массив, называется неопределенным поведением.
В частности, когда вы выделяете массив необработанных типов данных (ints), компилятору не нужно много работать, поэтому он превращает его в простой malloc(), поэтому удаление p, вероятно, будет работать.
delete p не удастся, как правило, когда:
Использование delete с [] указывает компилятору вызывать деструктор для каждого элемента массива. Не использование delete [] может вызвать утечку памяти, если он используется в массиве объектов, которые используют динамическое распределение памяти, как показано ниже :
class AClass
{
public:
AClass()
{
aString = new char[100];
}
~AClass()
{
delete [] aString;
}
private:
const char *aString;
};
int main()
{
AClass * p = new AClass[1000];
delete p; // wrong
return 0;
}
Это называется неопределенное поведение ; это может сработать, но вы не знаете почему, поэтому не стоит его придерживаться.
Я не думаю, что Visual Studio отслеживает, как вы распределяли объекты, в виде массивов или простых объектов, и волшебным образом добавляет []
к вашему удалению. Вероятно, он компилирует delete p;
в тот же код, как если бы вы разместили с помощью p = new int
, и, как я уже сказал, по какой-то причине он работает. Но вы не знаете почему.
Нет, это неопределенное поведение. Не делайте этого - используйте delete[]
.
В VC++ 7 to 9 он работает , когда рассматриваемый тип имеет тривиальный деструктор, но он может перестать работать на более новых версиях - обычные вещи с неопределенным поведением. Не делайте этого в любом случае.
нет, вы должны использовать delete[]
при работе с массивами
Простое использование delete
не вызовет деструкторы объектов в массиве. Хотя он , возможно, будет работать так, как задумано, он не определен, поскольку есть некоторые различия в том, как именно они работают. Так что вы не должны использовать его даже для встроенных типов .
Один из ответов - да, это может вызвать утечку памяти, поскольку не вызывает деструктор для каждого элемента в массиве. Это означает, что любая дополнительная память, принадлежащая элементам в массиве, будет протекать.
Более соответствующий стандартам ответ - это неопределенное поведение. Компилятор, например, имеет полное право использовать пулы памяти для массивов, отличные от пулов памяти для элементов, не являющихся массивами. Выполнение нового одного способа, а удаление другого может привести к повреждению кучи.
Ваш компилятор может гарантировать, что стандарт этого не делает, но первая проблема остается. Для элементов POD, которые не владеют дополнительной памятью (или ресурсами, такими как дескрипторы файлов), все может быть в порядке.
Даже если это безопасно для вашего компилятора и элементов данных, все равно не делайте этого - это также вводит в заблуждение всех, кто пытается прочитать ваш код.
Причина, по-видимому, не в утечке памяти, потому что удаление обычно основано на свободном состоянии, которое уже знает, сколько памяти необходимо освободить. Однако часть c ++ вряд ли удастся правильно очистить. Готов поспорить, что вызывается только деструктор первого объекта.