2009-05-12 14 views
7

Przeszliśmy przez dużą analizę wycieków pamięci i stwierdziliśmy, że jednym z czynników przyczyniających się do tego było nieusuwanie delegatów na wydarzenia powodując, że obiekty nie ulegają GCed wystarczająco szybko (lub czasami na zawsze).Wszelkie pomysły dotyczące zapisu reguły analizy statycznej (FXCop) w celu usunięcia delegatów zdarzeń

Czy ktoś ma jakieś pomysły, jak napisać regułę w FXCop, aby upewnić się, że mamy delegatów są usuwane z obsługi?

Właśnie widziałem this i jako takie będę tam poprosić o więcej informacji.

Odpowiedz

2

Ok, obok problemu wdrażania rzeczywistą kontrolę (moim zdaniem jest bardzo podobny do path coverage i dlatego nie praktyczne) - tutaj jest sposób, aby napisać nową FxCop wykluczyć go:

Początkowo niektóre artykuły, które pomogły mi kiedyś:

Wdrożenie prostej zasady to nic wielkiego. W projekcie potrzebny jest plik Rules.xml jako zasób osadzony (patrz here).Czerpać swoją klasę z BaseIntrospectionRule i dodać kod do wyboru() - metoda:

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

Zrobiłem to kilka razy wcześniej. Mam nadzieję, że nadal działa zgodnie z opisem :)

+0

dziękuję, to jest najbliższe odpowiedzi, której szukałem. Ale w uczciwości inne odpowiedzi są również prawdziwe, a tam, gdzie to możliwe, wdrażamy słabe referencje. –

0

Czy można bezpiecznie założyć, że obiekty implementujące procedury obsługi mają odwołania do obiektu ze zdarzeniami? Jeśli tak jest, lepiej jest zastanowić się, jak przerwać cykl w inny sposób.

Coś podobnego działo się jakiś czas temu z obsługą zdarzeń na stronach ASP.NET. Obiekty, które zaimplementowały procedury obsługi miały również odniesienia do stron. Po zerwaniu jak największej liczby linków, tak jak byśmy mogli, kilka lewicowań zmieniono na WeakReferences. Koniec z problemami z pamięcią!

+0

Ciekawe ... dziękuję. –

3

Musisz być bardziej szczegółowy. Nie musisz sprawdzać, czy wszyscy uczestnicy wydarzenia zostali anulowani, ponieważ w zwykłym przypadku subskrybent ma krótsze życie niż wydawca. A przeciek pamięci występuje tylko wtedy, gdy subskrybent wydaje się być dłużej żywy niż wydawca, dlatego istnieje odniesienie, które uniemożliwia GC zbieranie obiektu wydawcy.

Teraz musimy sprawdzić, czy subskrybując wydarzenie na stosunkowo krótkim obiekcie, w końcu zrezygnujesz z subskrypcji.

Heurystyki, które mogę wymyślić w tym przypadku: przeanalizuj wszystkie obiekty zmiennych lokalnych (które są ograniczone zakresem obecnego bloku kodu {}) i wszystkie obiekty, które jawnie usuniesz. Dla każdego wydarzenia na tych obiektach policz ile razy je zasubskrybowałeś i ile razy zrezygnujesz z subskrypcji. Jeśli pierwsza liczba jest większa, wyślij ostrzeżenie.

Oczywiście, że nie obejmuje wszystkich przypadków, ale myślę, że żadne podejście statyczne nie może obejmować wszystkich przypadków w tym problemie, potrzebujesz pewnej metody, która jest wystarczająco dobra.

Nie będę tu wspominał o zaletach analizy dynamicznej i recenzji kodu, ponieważ jest to osobny temat, niezwiązany z pytaniem.

+0

Dziękuję. Doceniam szczegółową odpowiedź. Jestem dość pewny rzeczy, które chcę sprawdzić. Chciałbym się dowiedzieć, jak to zrobić w regule FX. Nie mogę znaleźć odpowiednich informacji o tym, jak używać zespołów FX do pisania nowych złożonych reguł. –

1

Czy można wymusić zasadę, że wszystkie subskrypcje zdarzeń powinny być obsługiwane za pośrednictwem WeakReferences? Myślę, że powinno to być łatwiejsze do wdrożenia niż analiza rzeczywistego przepływu programu.