2009-03-24 9 views
34

En mi función C++ main, por ejemplo, si tuviera un puntero a una variable que utiliza memoria de pila (a diferencia de la memoria de pila), ¿esto se desasigna automáticamente después de que se cierra mi aplicación? Yo asumiría eso.¿Hay alguna razón para llamar a eliminar en C++ cuando un programa sale de todos modos?

Aun así, ¿es una buena práctica eliminar siempre las asignaciones de pila incluso si piensa que nunca se utilizarán en una situación en la que la memoria se desasigna automáticamente al salir?

Por ejemplo, ¿hay algún punto para hacer esto?

int main(...) 
{ 
    A* a = new A(); 
    a->DoSomething(); 
    delete a; 
    return 0; 
} 

estaba pensando tal vez en caso de que refactorizar (o alguien refactors más) que el código y lo pone en otra parte de la aplicación, donde delete es realmente neccecary.

Además de la respuesta de Brian R. Bondy (que habla específicamente sobre las implicaciones en C++), Paul Tomblin también tiene un good answer to a C specific question, que también habla sobre el destructor de C++.

+0

El duplicado mencionado es sobre C, que se pierde en alguna información importante sobre el destructor que es un problema en C++. –

+0

@Brian, mi respuesta al duplicado también menciona destructores (ahora). Mi sentimiento de que este debería ser eliminado sigue en pie. –

+0

No estoy seguro de lo que quiere decir sobre destructor - aclare. –

Respuesta

61

Es importante llamar explícitamente a eliminar porque es posible que tenga algún código en el destructor que desea ejecutar. Como escribir algunos datos en un archivo de registro. Si deja que el sistema operativo libere su memoria, su código en su destructor no se ejecutará.

La mayoría de los sistemas operativos desasignarán la memoria cuando finalice su programa. Pero es una buena práctica desasignarlo usted mismo y, como dije antes, el sistema operativo no llamará a su destructor.

En cuanto a la llamada a la eliminación en general, sí siempre quiere llamar a borrar, o de lo contrario tendrá una pérdida de memoria en su programa, lo que dará lugar a nuevas asignaciones que fallan.

+9

No olvide que un miembro de la clase también puede tener algo que no desaparece automáticamente al finalizar el programa, como un socket o conexión o algo así. La memoria no es lo único que se escapa, y no todas las fugas pueden limpiarse automáticamente. –

+0

¿Qué pasa si tengo memoria asignada para Tree (específicamente trie), y dentro de destructor, todo lo que tengo que hacer es 'delete'. ¿Todavía necesito llamar explícitamente a eliminar? o confiar en OS para hacer por mí? –

6

Piensa en tu clase A teniendo que destruir.
Si no llama al delete en a, no se llamará al destructor. Generalmente, eso no importará realmente si el proceso finaliza de todos modos. Pero, ¿qué ocurre si el destructor tiene que liberar, p. objetos en una base de datos? ¿Vaciar una caché a un archivo de registro? Escribir una memoria caché de nuevo en el disco?

Como ve, no es solo una "buena práctica" eliminar objetos, en algunas situaciones es necesario.

7

Considere el caso en el que el objeto a eliminar adquirió un recurso externo que el SO no puede liberar de forma segura. Si no llama a eliminar en ese objeto, tiene una fuga real.

2

siempre asegúrese de eliminarlo usted mismo. Un sistema operativo se encargará de esto, pero para excluir errores que pueden evitarse fácilmente

21

Sí, ayuda a eliminar los falsos positivos cuando ejecuta su programa a través de una herramienta de detección de fuga de memoria.

+1

¿Podría indicarme algunas buenas herramientas de detección de fugas? –

+1

En Windows, BoundsChecker de Compuware es excelente, pero costoso. En Linux, he escuchado cosas buenas sobre Valgrind, pero aún no lo he probado. – Ferruccio

+2

Uno gratuito para MSVC++ es Visual Leak Detector (ejecuta una búsqueda en Internet; lo encontrarás fácilmente) –

3

Otra razón para eliminar explícitamente objetos es que si su aplicación tiene una pérdida de memoria real, es más fácil usar herramientas como valgrind para encontrar las fugas si no tiene que pasar por "fugas" que provienen de no molestar limpiar.

3

Otro motivo para eliminar es evitar falsas alarmas de un detector de fugas que pueda usar en el futuro. Si tiene falsas alarmas, puede que no preste atención a una fuga real informada por un detector de fugas: se ocultará entre las falsas en el informe.

+1

Para ser justos, dado el código del OP, estas no serían alarmas "falsas";) –

9

Sí.

  • la norma no garantía de que el sistema operativo va a limpiar la memoria. Puede esperar esto en las principales plataformas, pero ¿por qué arriesgarse?
  • Minimiza el desorden informado por herramientas como valgrind si no pierde memoria deliberadamente.
  • Si te metes en este hábito, ¿quién puede decir que un día no aplicarás accidentalmente este enfoque en algún lugar importante?
  • Usted puede necesidad de destrucción de objetos. Por lo general solo asume que lo haces. No te lastima.
+1

El punto n. ° 3 es el más convincente para mí. Es menos esfuerzo eliminar siempre las asignaciones que intentar y siempre decidir cuándo es apropiado. Me recuerda el uso de las señales de giro del automóvil: siempre me pregunté por qué las personas se molestaban en usarlo * algunas veces *; es mejor que sea un hábito donde no tienes que pensar en absoluto. – tenfour

+0

@tenfour: De hecho. Si no puede garantizar que el automóvil que tiene delante siempre lo indique cuando corresponda, entonces no puede estar seguro de cuándo no está girando. Todo el sistema se descompone. –

+0

@LightnessRacesinOrbit: +1 por decir que "El estándar no garantiza que el sistema operativo limpiará la memoria". También me gusta tu tercer punto. – Destructor

Cuestiones relacionadas