2011-07-04 10 views
5

duplicados posibles:
Is it possible to have a memory leak in managed code? (specifically C# 3.0)
Memory Leak in C#Cómo crear una pérdida de memoria en C#/.NET

Hubo una pregunta similar sobre esto ayer, pero para Java, por lo que Estoy interesado: ¿qué se necesita para crear una pérdida de memoria en C#/.NET (sin usar inseguro)?

+1

Algunas de las respuestas en este hilo son políticas, para ver un ejemplo real, consulte aquí: http://smartbear.com/support/articles/aqtime/net-allocation-profiler/ - "Obviamente, este controlador no se elimina del evento dado, lo que da como resultado una fuga". –

Respuesta

12

eventos estáticos; MORTAL, ya que nunca salen de su alcance.

static event EventHandler Evil; 

for(int i = 0 ; i < 1000000 ; i++) 
    Evil += delegate {}; 

El método anónimo es simplemente una agradable a tener aquí, pero son agradables porque también son un cerdo para cancelar la suscripción a menos que tome una copia en un/campo variable y suscribirse que.

Técnicamente esto no es en realidad "filtrado", como todavía se puede acceder a ellos a través de Evil.GetInvocationList() - sin embargo, cuando se utiliza con objetos normales que esto puede causar tiempos de vida de objetos inesperados, es decir

MyHeavyObject obj = ... 
... 
SomeType.SomeStaticEvent += obj.SomeMethod; 

ahora el objeto al obj vive para siempre. Esto satisface suficiente de pérdida percibida IMO, y "mi aplicación murió una muerte horrible" es suficiente para mí; p

+0

pero todavía se puede llegar a ellos ... ¿no? –

+1

Sí, he tenido que arreglar esto * una vez * antes ... exactamente una vez, porque eso no volverá a suceder =) –

+0

@Adam Ralph: todos los suscriptores se mantendrán indefinidamente (a menos que no estén registrados en el evento) porque evento es estático. –

5

Cuando un objeto se suscribe a un evento, el objeto que expone el evento mantiene una referencia al suscriptor (en realidad, el evento, el MultiCastDelegate originalmente lo hace, pero se transmite). Esta referencia impedirá que el suscriptor sea GC'd si la última referencia (distinta de la que mantiene el event) queda fuera del alcance.

Las otras dos respuestas tienen esta situación completamente atrasada y son incorrectas. Esto es un poco difícil de mostrar en un ejemplo simple y se ve típicamente en proyectos más grandes, pero recuerde que una referencia al suscriptor es mantenida por el MultiCastDelegate (event) y debería poder pensarlo detenidamente.

EDIT: Como Marc menciona en su respuesta que técnicamente podría obtener una referencia al objeto "filtrado" a través del método GetInvocationList(), pero su código es poco probable que sea el uso que y no va a importar cuando te estrellas con un OutOfMemoryExcetion .

+0

muy cierto y estoy completamente de acuerdo, pero debemos tener en cuenta que esto no responde a la pregunta –

+0

@ Adam Ralph: ¿No? Describe una forma de perder memoria. ¿Cómo evita eso responder a la pregunta? –

+0

No estoy de acuerdo con que esté describiendo una pérdida de memoria.Una pérdida de memoria implica que el GC está roto, ya que no está liberando toda la memoria utilizada por los objetos sin raíz. En la situación que describe, las referencias y tiempos de vida se mantienen correctamente y el GC mantiene vivos todos los objetos que debería. –

1

El acceso directo a la memoria se extrae del código administrado seguro. Tiene que haber una llamada a un código inseguro en alguna parte para inducir fugas de memoria, ya sea en el código que escribe o en un recurso de terceros (posiblemente dentro de la FCL) con un error de fuga de memoria.

Cuestiones relacionadas