2009-05-12 8 views
7

Hemos estado pasando por un gran análisis de fuga de memoria y hemos encontrado que uno de los factores contribuyentes ha sido la no eliminación de delegados en eventos causando que los objetos no sean GCed lo suficientemente rápido (o a veces para siempre).Cualquier idea sobre cómo escribir una regla de análisis estático (FXCop) para asegurar que los delegados de eventos se eliminen

¿Alguien podría tener alguna idea sobre cómo escribir una regla en FXCop para garantizar que los delegados se eliminen de los controladores?

Acabo de ver this y, como tal, le pediré más información.

Respuesta

2

Ok, junto al problema de la aplicación de la verificación real (en mi opinión, esto es muy similar a un path coverage y por lo tanto no es práctico) - Esta es la forma de escribir un nuevo FxCop descartarlo:

Al principio, algunos artículos que me ayudaron una vez:

La implementación de una regla simple no es gran cosa. En su proyecto, necesita un archivo Rules.xml como recurso incrustado (consulte here).Que se derivan de su clase de BaseIntrospectionRule y agregar el código para la comprobación() - Método:

public override ProblemCollection Check(TypeNode typeNode) 
{ 
    if(type.IsPublic) 
    { 
    Problems.Add(new Problem(...)); 
    } 
    return Problems; 
} 

lo hice hace unos momentos. Espero que todavía funcione como se describe :)

+0

gracias esto es lo más cercano a la respuesta que estaba buscando. Pero para ser justos, las otras respuestas también son ciertas, y estamos implementando referencias débiles siempre que sea posible. –

0

¿Es seguro asumir que los objetos que implementan los manejadores tienen de alguna manera referencias al objeto con los eventos? Si ese es el caso, es mejor que descubras cómo romper el ciclo de otra manera.

Tuvimos algo similar hace un tiempo con controladores de eventos en páginas ASP.NET. Los objetos que implementaron los controladores también tenían referencias a las páginas. Después de romper la mayor cantidad posible de enlaces, los pocos sobrantes se cambiaron a WeakReferences. ¡No más problemas de memoria!

+0

Interesante ... gracias. –

3

Tiene que ser más específico. No es necesario verificar que TODOS los delegados al evento hayan sido cancelados, porque en un caso común, un suscriptor tiene una vida más corta que un editor. Y una pérdida de memoria solo ocurre cuando su suscriptor parece tener una vida más larga que un editor, por lo tanto, hay una referencia que impide que GC recopile el objeto editor.

Ahora tenemos que verificar que si se suscribe a un evento en un objeto de vida relativamente corta, se da de baja eventualmente.

Una heurística que se me ocurre en este caso: analizar todos los objetos de variables locales (que tienen el ámbito del bloque de código actual {}) y todos los objetos que explícitamente se descartan. Para cada evento en estos objetos, cuente la cantidad de veces que se suscribe y la cantidad de veces que se da de baja. Si el primer número es mayor, emita una advertencia.

Por supuesto que no cubre todos los casos, pero supongo que ningún enfoque estático puede cubrir todos los casos en este problema, necesita algún método que sea lo suficientemente bueno.

No mencionaré aquí las ventajas del análisis dinámico y las revisiones de códigos, ya que se trata de un tema separado, no relacionado con la pregunta.

+0

Gracias. Agradezco la respuesta detallada. Estoy bastante seguro de las cosas que quiero verificar. Lo que me gustaría averiguar es información sobre cómo hacer esto en una regla de FX. Parece que no puedo encontrar información decente sobre cómo usar los conjuntos FX para escribir nuevas reglas complejas. –

1

¿Se puede forzar una regla de que todas las suscripciones de eventos se deben manejar a través de WeakReferences? Estoy pensando que esto debería ser más fácil de implementar que tener que analizar el flujo real de su programa.

Cuestiones relacionadas