Я проверил следующий код на С++ с valgrind с --leak-check=full, и он говорит, что утечка памяти отсутствует. Почему это?
char *p = new char[256];
delete p;
Насколько мне известно, new[] должен соответствовать delete[].
Я проверил следующий код на С++ с valgrind с --leak-check=full, и он говорит, что утечка памяти отсутствует. Почему это?
char *p = new char[256];
delete p;
Насколько мне известно, new[] должен соответствовать delete[].
Хотя поведение undefined как @KillianDS говорит, разница, вероятно, связана с тем, что обе delete и delete[] освобождают базовую память. Точка delete[] заключается в том, что деструкторы для каждого объекта в массиве вызываются до освобождения памяти. Поскольку char является POD и не имеет деструктора, в этом случае нет никакой эффективной разницы между ними.
Однако вы определенно не должны полагаться на это.
delete и delete[] будут равны, только если p указывает на основные типы данных, такие как char или int.
Если p указывает на массив объектов, результат будет другим. Попробуйте использовать код ниже:
class T {
public:
T() { cout << "constructor" << endl; }
~T() { cout << "destructor" << endl; }
};
int main()
{
const int NUM = 3;
T* p1 = new T[NUM];
cout << p1 << endl;
// delete[] p1;
delete p1;
T* p2 = new T[NUM];
cout << p2 << endl;
delete[] p2;
}
Используя delete[], будут задействованы все деструкторы T в массиве. С помощью delete вызывается только p[0] деструктор.
Когда я пытаюсь это сделать, valgrind сообщает:
==22707== Mismatched free() / delete / delete []
==22707== at 0x4C2B59C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22707== by 0x40066D: main (in /home/andrew/stackoverflow/memtest)
==22707== Address 0x5a1a040 is 0 bytes inside a block of size 256 alloc'd
==22707== at 0x4C2C037: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22707== by 0x40065D: main (in /home/andrew/stackoverflow/memtest)
Это не утечка памяти, но valgrind замечает проблему.
Потому что это поведение undefined. В вашем случае delete может выполнять работу delete [] в вашем компиляторе, но может не работать на другой машине.
Это undefined поведение, поэтому мы не можем рассуждать о его поведении. Если мы рассмотрим проект стандартного раздела С++ 3.7.4.2 Deallocation, в пункте 3 говорится (выделено мной):
[...] В противном случае поведение undefined, если значение, предоставленное оператору delete (void *) в стандартной библиотеке, не является одним из значений, возвращаемых предыдущим вызовом любого оператора new ( std:: size_t) или оператор new (std:: size_t, conststd:: nothrow_t &) в стандартной библиотеке, а поведение undefined, если значение, предоставленное оператору delete [] (void *) в стандартная библиотека не является одним из значений, возвращаемых предыдущим вызовом любого оператора new [] (std:: size_t) или оператора new [] (std:: size_t, const std:: nothrow_t &) в стандартная библиотека.
Фактические данные будут поведение, определяемое реализацией, и могут сильно различаться.
Разница между delete и delete [] заключается в том, что компилятор добавляет код для вызова деструктора для удаления объектов. Скажите примерно так:
class A
{
int a;
public:
...
~A() { cout<<"D'tor"; }
};
a=new A[23];
delete [] a;
Этот delete [] a; преобразуется в нечто вроде <
for (int i=0; i<23; i++)
{
a[i].A::~A();
}
std::delete a;
Итак, для вашего случая, так как это встроенный тип данных, деструктор для вызова не существует. Таким образом, он преобразуется как
std::delete a;
который intern вызывает free(), чтобы освободить память. Это причина, по которой вы не получаете утечки. Поскольку выделенная память полностью освобождается, используя free() в g++.
Но лучше всего использовать версию delete [], если вы используете new [].