repentina por perdida para memoria medicamentos jovenes inmediata golpe estres enfermedad caracteriza ancianos c++ memory-leaks valgrind

c++ - perdida - ¿Por qué este código no produce una pérdida de memoria?



perdida de memoria repentina (6)

Aunque es un comportamiento indefinido como dice @KillianDS, la diferencia probablemente se relaciona con el hecho de que tanto delete como delete[] liberan la memoria subyacente. El punto de delete[] es que se llama a los destructores para cada objeto de la matriz antes de liberar la memoria. Dado que char es un POD y no tiene un destructor, no hay ninguna diferencia efectiva entre los dos en este caso.

Sin embargo, definitivamente no deberías confiar en ello.

Esta pregunta ya tiene una respuesta aquí:

Verifiqué el siguiente código en C ++ con valgrind con --leak-check=full y dice que no hay pérdida de memoria. ¿Porqué es eso?

char *p = new char[256]; delete p;

new[] debe coincidir con delete[] hasta donde sé.


Cuando intento esto, valgrind informa:

==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//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//memtest)

No es realmente una pérdida de memoria, pero valgrind nota el problema.


Este es un comportamiento indefinido , por lo que no podemos razonar sobre su comportamiento. Si observamos el borrador de la sección 3.7.4.2 norma C ++, funciones de desasignación , el párrafo 3 dice ( énfasis mío ):

[...] De lo contrario, el comportamiento no está definido si el valor suministrado al operador delete (void *) en la biblioteca estándar no es uno de los valores devueltos por una invocación previa del operador new (std :: size_t) o new operator (std :: size_t, conststd :: nothrow_t &) en la biblioteca estándar , y el comportamiento no está definido si el valor proporcionado al operador delete [] (void *) en la biblioteca estándar no es uno de los valores devueltos por una invocación previa de ya sea el operador new [] (std :: size_t) o el operador new [] (std :: size_t, const std :: nothrow_t &) en la biblioteca estándar.

Los detalles reales serán un comportamiento definido por la implementación y podrían variar mucho.


La diferencia entre delete y delete [] es que el compilador agrega código para llamar al destructor para eliminar objetos. Di algo como esto:

class A { int a; public: ... ~A() { cout<<"D''tor"; } }; a=new A[23]; delete [] a;

Esto delete [] a; se transforma en algo así como,

for (int i=0; i<23; i++) { a[i].A::~A(); } std::delete a;

Por lo tanto, para su caso, ya que se trata de un tipo de datos integrado, no hay un destructor al que llamar. Así, se transformó como,

std::delete a;

qué interno llama al free() para desasignar la memoria. Esa es la razón por la que no está recibiendo ninguna fuga. Dado que la memoria asignada se desasigna completamente usando free() en g ++.

Pero la mejor práctica es que tiene que usar la versión de delete [] si usa la new [] .


Porque es un comportamiento indefinido. En su caso, delete puede hacer el trabajo de delete [] en su compilador, pero puede que no funcione en otra máquina.


delete y delete[] será igual solo si la p apunta a tipos de datos básicos, como char o int.

Si p apunta a una matriz de objetos, el resultado será diferente. Pruebe el siguiente código:

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; }

Mediante el uso de delete[] se invocarán todos los destructores de T en la matriz. Usando delete solo se invocará el destructor p[0] .