Подтвердить что ты не робот

Почему этот код не приводит к утечке памяти?

Я проверил следующий код на С++ с valgrind с --leak-check=full, и он говорит, что утечка памяти отсутствует. Почему это?

char *p = new char[256];
delete p;
Насколько мне известно,

new[] должен соответствовать delete[].

4b9b3361

Ответ 1

Хотя поведение undefined как @KillianDS говорит, разница, вероятно, связана с тем, что обе delete и delete[] освобождают базовую память. Точка delete[] заключается в том, что деструкторы для каждого объекта в массиве вызываются до освобождения памяти. Поскольку char является POD и не имеет деструктора, в этом случае нет никакой эффективной разницы между ними.

Однако вы определенно не должны полагаться на это.

Ответ 2

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] деструктор.

Ответ 3

Когда я пытаюсь это сделать, 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 замечает проблему.

Ответ 4

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

Ответ 5

Это 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 &) в стандартная библиотека.

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

Ответ 6

Разница между 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 [].