[.net] Referencias circulares ¿Causa pérdida de memoria?


2 Answers

Como ya han dicho otros, GC no tiene problemas con las referencias circulares. Me gustaría agregar, que un lugar común para filtrar memoria en .NET son los manejadores de eventos. Si uno de sus formularios tiene un controlador de eventos adjunto a otro objeto que está "vivo", entonces hay una referencia a su formulario y el formulario no recibirá GC'd.

Question

Estoy tratando de ejecutar una pérdida de memoria en una aplicación de formularios de Windows. Estoy buscando ahora un formulario que contiene varias formas incrustadas. Lo que me preocupa es que los formularios secundarios, en su constructor, hagan referencia al formulario principal y lo mantengan en un campo privado. Entonces me parece que viene el tiempo de recolección de basura:

El padre tiene una referencia al formulario secundario, a través de la colección de controles (el formulario hijo está incrustado allí). La forma del niño no es GC'd.

El formulario hijo tiene una referencia al formulario padre, a través del campo de miembro privado. El formulario principal no es GC.

¿Es esto una comprensión precisa de cómo el recolector de basura evaluará la situación? ¿Alguna forma de "probarlo" para fines de prueba?




El GC puede tratar correctamente las referencias circulares y si estas referencias fueran las únicas que mantuvieran el formulario vivo, entonces serían recolectadas.
He tenido muchos problemas con .net al no recuperar memoria de formularios. En 1.1 hubo algunos errores alrededor de menuitem (creo) lo que significaba que no se eliminaban y podían perder memoria. En este caso, al agregar una llamada explícita para eliminar y borrar la variable miembro en el método Dispose del formulario, se solucionó el problema. Descubrimos que esto también ayudó a reclamar memoria para algunos de los otros tipos de control.
También pasé mucho tiempo con CLR Profiler mirando por qué los formularios no se estaban recopilando. Por lo que pude ver, el marco estaba manteniendo las referencias. Uno por tipo de formulario. Entonces, si crea 100 instancias de Form1, entonces ciérrelas todas, solo 99 se recuperarán correctamente. No encontré ninguna manera de curar esto.
Nuestra aplicación se ha movido a .net 2 y esto parece ser mucho mejor. La memoria de nuestra aplicación aún aumenta cuando abrimos el primer formulario y no retrocede cuando está cerrado, pero creo que esto se debe al código JIT y a las bibliotecas de control extra que están cargadas.
También encontré que aunque el GC puede tratar con referencias circulares, parece tener problemas (a veces) con referencias circulares de manejadores de eventos. IE object1 hace referencia a object2 y object1 tiene un método que maneja y evento desde object2. Encontré circunstancias en las que esto no liberaba los objetos cuando esperaba, pero nunca pude volver a producirlos en un caso de prueba.




Si no se hace referencia al padre y al hijo, sino que solo se referencian entre sí, reciben GCed.

Obtenga un generador de perfiles de memoria para verificar realmente su aplicación y responder a todas sus preguntas. Puedo recomendar http://memprofiler.com/




Related