2010-12-15 12 views

Respuesta

16

Si se produce una excepción entre la asignación y desasignación, se producirá pérdida de memoria.

void f1() { 
    int* ptr = new int; 

    // do something which may throw an exception 

    // we never get here if an exception is thrown 
    delete ptr; 
} 

Cada vez f1 termina con una excepción, 4 bytes se filtraron (suponiendo int es 4 byte).

+0

great point thanks watson – ashmish2

+3

... una de las razones por las que los punteros inteligentes son "más inteligentes" que los punteros sin formato como 'int *' (que no tienen destructor): http://stackoverflow.com/questions/106508/what-is -a-smart-pointer-and-when-should-i-use-one – HostileFork

13

una pérdida de memoria se produce cuando se colocan en la memoria, no tiene aún lo desasignó, y , nunca podrá desasignarlo porque ya no puede acceder a él.

Por ejemplo, el código siguiente provoca una pérdida de memoria de tamaño sizeof(int):

int * a = malloc(sizeof(int)); //allocate memory 
a = 0; //this will cause a memory leak 

Esto crea una pérdida de memoria, porque ahora nunca seremos capaces de anular la planificación de la memoria asignada para a.

2

A new sin un delete, un new[] sin un delete[], un malloc sin un free.

En serio, ¿qué más quieres escuchar?

6

También puede perder memoria cuando no desasignar algún otro recurso como no llamar fclose en un FILE * o algún otro mango biblioteca porque pueden asignar buffers de memoria que no se tiene acceso directo a su programa.

2

No hay ninguna otra razón para la desviación de memoria además de la que usted menciona

+0

Un contraejemplo para esto es la respuesta de watson1180. – Cam

+0

@Cam: No lo creo, en el ejemplo de watson1180, olvidó llamar a 'borrar' (aunque está escrito en el código). –

+0

@Matthieu: Hmm ... de hecho. Lamentablemente, actualmente no puedo desvincular la respuesta de beb0. – Cam

4

Digamos que ha creado una clase que hereda alguna otra clase que no tenga un destructor virtual. Si el tipo del puntero a esta clase no es la clase más derivada (esto generalmente ocurre si usa una fábrica abstracta), entonces solo se llamará al destructor del tipo de puntero y cualquier cosa que haya estado esperando liberar en la mayoría de los derivados el destructor de clase tendrá fugas.

Este es un error muy común y que algunas veces es difícil de ver.

De todos modos, si se quiere evitar pérdidas de memoria con C++ sigue estas reglas:

  • Prefiero pasar referencias en lugar de punteros
  • Uso puntero inteligente siempre que sea posible (ver: shared_ptr)
+0

por supuesto, el estándar dice que es un comportamiento indefinido si el destructor de la clase base no es virtual, entonces estás manipulando el mal y una pérdida de memoria es la menor de tu preocupación aquí. En cuanto a 'shared_ptr', a veces es útil, pero hay muchos mejores punteros/contenedores inteligentes para uso diario. Sin duda debería ser la última opción. –

0

Me sorprende que nadie haya mencionado la corrupción en la memoria todavía.

Recuerdo un caso cuando teníamos un asignador de memoria de bloques de tamaño fijo implementado como una lista vinculada.

Algunos tipos habían estropeado los cálculos de tamaño, lo que llevó a copiar datos solo un par de bytes más allá del tamaño máximo del bloque (los apuntadores tenían solo 2 bytes de longitud en el momento :)). A continuación, sobrescribía el enlace "siguiente" ubicado al comienzo del siguiente bloque libre con basura que se llenó con ceros.

Esto tuvo la consecuencia de cortar la cadena de bloques libres. Como en ese punto los otros componentes del software mantenían sus propios indicadores de los bloques que estaban usando, el programa parecía funcionar bien.

Pero, por supuesto, la lista se quedó corta de unas pocas cuadras de vez en cuando, y esta fuga eventualmente agotó los bloques libres, muriendo de hambre la aplicación.

0

El siguiente ejemplo, escrito en pseudocódigo, tiene como objetivo mostrar cómo se puede producir una pérdida de memoria y sus efectos, sin necesidad de ningún conocimiento de programación. El programa en este caso es parte de un software muy simple diseñado para controlar un ascensor. Esta parte del programa se ejecuta cada vez que alguien dentro del ascensor presiona el botón de un piso.

Cuando se pulsa un botón:

Get some memory, which will be used to remember the floor number 
    Put the floor number into the memory 
    Are we already on the target floor? 
    If so, we have nothing to do: finished 
    Otherwise: 
     Wait until the lift is idle 
     Go to the required floor 
     Release the memory we used to remember the floor number 

La pérdida de memoria se produciría si el número del piso solicitada es la misma planta que el ascensor está encendido; la condición para liberar la memoria se omitirá. Cada vez que ocurre este caso, se filtra más memoria.

Cuestiones relacionadas