32 votos

Es delete[] igual a borrar?

IP_ADAPTER_INFO *ptr=new IP_ADAPTER_INFO[100];

si yo uso libre

delete ptr;

va a conducir a la pérdida de memoria, si no, ¿por qué ?

Este es el desmontaje código generado por VS2005

**delete ptr;**
0041351D  mov         eax,dword ptr [ptr] 
00413520  mov         dword ptr [ebp-0ECh],eax 
00413526  mov         ecx,dword ptr [ebp-0ECh] 
0041352C  push        ecx  
0041352D  call        operator delete (4111DBh) 
00413532  add         esp,4 
    **delete []ptr;**
00413535  mov         eax,dword ptr [ptr] 
00413538  mov         dword ptr [ebp-0E0h],eax 
0041353E  mov         ecx,dword ptr [ebp-0E0h] 
00413544  push        ecx  
00413545  call        operator delete[] (4111E5h) 
0041354A  add         esp,4

130voto

sbi Puntos 100828

Si esto conduce a una pérdida de memoria, borra su disco duro, usted obtiene embarazada, hace desagradable Nasal Demonios que te persiguen alrededor de su apartamento, o permite que todo funcione correctamente, sin problemas aparentes, es indefinido. Podría ser de esta manera con un compilador, y cambian con el otro, en cambio con una nueva versión del compilador, con cada nueva compilación, con las fases de la luna, su estado de ánimo, o dependiendo de la cantidad o de neutrinos que pasa a través del procesador en la última tarde de sol. O puede que no.

Todo eso, y un número infinito de posibilidades se ponen en un término: Indefinido comportamiento:

Sólo se mantenga alejado de ella.

4voto

jichi Puntos 561

Sólo una ilustración de algunos "undefined" comportamientos en ciertos sistemas operativos y compiladores. La esperanza de que podría ser útil para las personas a depurar su código.

Prueba 1

#include <iostream>
using namespace std;
int main()
{
  int *p = new int[5];
  cout << "pass" << endl;
  delete p;
  return 0;
}

Prueba 2

#include <iostream>
using namespace std;
int main()
{
  int *p = new int;
  cout << "pass" << endl;
  delete[] p;
  return 0;
}

Prueba 3

#include <iostream>
using namespace std;
struct C {
  C() { cout << "construct" << endl; }
  ~C() { cout << "destroy" << endl; }
};

int main()
{
  C *p = new C[5];
  cout << "pass" << endl;
  delete p;
  return 0;
}

Prueba 4

#include <iostream>
using namespace std;
struct C {
  C() { cout << "construct" << endl; }
  ~C() { cout << "destroy" << endl; }
};

int main()
{
  C *p = new C;
  cout << "pass" << endl;
  delete[] p;
  return 0;
}
  • Windows 7 x86, msvc 2010. Compilar con las opciones por defecto, es decir, controlador de excepciones está habilitado.

Prueba 1

pass

Prueba 2

pass

Prueba 3

construct
construct
construct
construct
construct
pass
destroy
# Then, pop up crash msg

Prueba 4

construct
pass
destroy
destroy
destroy
destroy
destroy
destroy
destroy
... # It never stop until CTRL+C
  • Mac OS X 10.8.5, llvm-gcc 4.2 o gcc-4.8 generar el mismo resultado

Prueba 1

pass

Prueba 2

pass

Prueba 3

construct
construct
construct
construct
construct
pass
destroy
a.out(71111) malloc: *** error for object 0x7f99c94000e8: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
zsh: abort      ./a.out

Prueba 4

construct
pass
a.out(71035) malloc: *** error for object 0x7f83c14000d8: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
zsh: abort      ./a.out
  • Ubuntu 12.04, AMD64, gcc 4.7

Prueba 1

pass

Prueba 2

pass

Prueba 3

construct
construct
construct
construct
construct
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x0000000001f10018 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7fe81d878b96]
./a.out[0x400a5b]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fe81d81b76d]
./a.out[0x4008d9]
======= Memory map: ========
....
zsh: abort (core dumped)  ./a.out

Prueba 4

construct
destroy
destroy
destroy
destroy
destroy
destroy
destroy
destroy
...
destroy
destroy
*** glibc detected *** ./a.out: free(): invalid pointer: 0x00000000016f6008 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7fa9001fab96]
./a.out[0x400a18]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fa90019d76d]
./a.out[0x4008d9]
======= Memory map: ========
...
zsh: abort (core dumped)  ./a.out

3voto

Andrejs Cainikovs Puntos 7758

Si apunta a una matriz que se ha asignado a través de las nuevas T[n], entonces usted debe eliminar a través delete[] A.

Por qué?

La diferencia entre delete y delete[] es sencilla - el ex destruye un escalar el objeto y el segundo destruye una matriz.

Más info aquí y aquí.

ACTUALIZACIÓN 1 (malo):

Si utiliza eliminar (y no delete []), mientras que con la asignación de nuevas T[n], sólo el primer elemento es liberado, mientras que otros no destructorized, lo que conducirá a la pérdida de memoria. Por qué? Esta es la forma en que Bjarne Stroustrup y otros habían diseñado el idioma. Y no es por el compilador diferentes. Si un compilador desasigna la diferente forma, es sólo que no sigue el estándar. El Lenguaje de Programación C++ , capítulos 6.2.6.2 y 19.4.5.

ACTUALIZACIÓN 2 (correcto):

Estoy admitir mi error acerca de la conducta de uso de operador delete en las asignaciones con las nuevas T[n]. La lectura del mencionado documento no encontré la descripción exacta, así que supongo que en esta situación, el comportamiento será indefinido y varían según el compilador. AFAIK, MSVC compilador, por ejemplo, se producen diferentes de código de GCC. Por favor, ignorar la ACTUALIZACIÓN 1.

3voto

sharptooth Puntos 93379

Normalmente no se fuga porque en el caso de la VAINA de los destructores son triviales y no hay necesidad de invocar de modo delete sólo cancela la asignación de memoria ocupado por la matriz. Desasignación de memoria, sólo se requiere un valor de puntero, así que será devuelto al montón. La matriz accopies un bloque contiguo de memoria y por lo tanto la cancelación puede ser exitoso como si fuera un desasignación de un solo elemento.

Pero no confíe en esto ya que es un comportamiento indefinido. Tal vez se trabaja bien, tal vez algo horrible sucede, trabaja en este compilador, no funciona en el otro y muchas personas gracias por la plantación de un error.

Ver esta respuesta para más detalles.

2voto

FranckSpike Puntos 26

eliminar: llama a la adecuada destructor sólo para el elemento señalado (si es necesario), luego se libera la memoria del pedazo de

delete[]: llama a la adecuada destructores de cada elemento en su matriz (si es necesario), luego se libera la memoria del pedazo de

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X