2010-04-30 14 views
22
int main(){ 
Employee *e = new Employee(); 

delete e; 
delete e; 
... 
delete e; 
return 0; 

} 
+4

casi siempre se bloquea ... – SysAdmin

+3

* error de pepino * reiniciar universo. –

+4

¿Por qué el voto a favor? Es una pregunta simple y directa. El hecho de que piense que es una pregunta elemental no significa que deba ser transmitida. –

Respuesta

37

e no es una referencia, es un puntero. Obtendrá comportamiento indefinido si intenta delete un objeto a través de un puntero más de una vez.

Esto significa que casi todo puede pasar de 'aparecer al trabajo' a 'estrellarse' o algo completamente al azar.

+0

Lo he probado y no se cuelga.Pero lo que creo es que puede desasignar la memoria que está usando otra parte de su programa. – flopex

+2

Puede que no se bloquee en ese momento. Pero si corrompe parte del montón, entonces hay una gran posibilidad de que se produzca un bloqueo en algún punto arbitrario después. Sin embargo, podría convertirse en una especie de bomba de relojería al acecho. No causará ningún problema hasta más tarde cuando una acción aparentemente no relacionada toque la parte dañada y luego * boom * – TheUndeadFish

4

es probable aventurarse en el territorio de un comportamiento indefinido '.

En muchos sistemas esto causará un bloqueo; por ejemplo, en mi máquina Linux:

*** glibc detected *** ./cctest: double free or corruption (fasttop): 0x0000000000d59900 *** 
======= Backtrace: ========= 
/lib/libc.so.6[0x7f399f4cbdd6] 
/lib/libc.so.6(cfree+0x6c)[0x7f399f4d074c] 
./cctest[0x400a7a] 
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f399f474abd] 
./cctest[0x400959] 
11

Aparte del viejo dicho de "un comportamiento indefinido" significa cualquier cosa podría pasar de la nada a una puerta de entrada al séptimo círculo de la apertura infierno en la memoria principal, en la práctica lo que generalmente sucederá en la mayoría de las implementaciones es que el programa continuará ejecutándose después de las eliminaciones, y luego colapsará misteriosamente en algún momento posterior en alguna asignación de memoria no relacionada.

+0

Sí, y esa es una de las mejores cosas que puede suceder. –

+3

a menudo Cuando obtengo los misteriosos accidentes de memoria, * DESEO * una puerta de entrada al séptimo círculo del infierno se abrió en la memoria principal ... –

18

Es un comportamiento indefinido, por lo que cualquier cosa puede suceder.

Lo que es probable que suceda es malo. Normalmente, la tienda gratuita es un sistema cuidadosamente administrado de bloques asignados y gratuitos, y new y delete hacen la contabilidad para mantener todo en un estado consistente. Si vuelve a delete, es probable que el sistema haga la misma contabilidad en datos no válidos y, de repente, la tienda gratuita se encuentra en un estado incoherente. Esto se conoce como "corrupción de montón".

vez que esto sucede, cualquier cosa que se hace con new o delete puede tener resultados impredecibles, que pueden incluir intentar escribir fuera del área de memoria de la aplicación, en silencio corromper los datos, pensando erróneamente que no hay más memoria, o la asignación doble o superpuestos. Si tiene suerte, el programa fallará pronto, aunque todavía tendrá problemas para descubrir por qué. Si no tiene suerte, seguirá funcionando con malos resultados.

3

Si tiene mucha suerte, se bloqueará. Lo que normalmente sucede es que acumula karma hasta que su CEO le muestra el código a su nuevo cliente más importante cuando corrompe/destruye todos sus datos.

En compilaciones comprobadas o depuradas a menudo este tipo de cosas se detectan, pero pueden pasar desapercibidas y causar estragos más adelante. Esto es especialmente profundo cuando se involucran múltiples hilos.

2

Si le preocupa que esto podría ocurrir en sus aplicaciones, ya sea dejar de usar punteros primas por completo, de modo que no es necesario eliminar (por ejemplo, cambiar a shared_ptr) o siempre punteros conjunto de NULL (o 0, o mejor aún nullptr) después de eliminarlos. Llamar a eliminar en un puntero nulo está garantizado para no hacer nada.

+3

Siempre me ha disgustado la última solución. Eliminar un puntero dos veces es malo, y establecer los punteros en nulo solo ocultará el problema. – GManNickG

Cuestiones relacionadas