2011-06-29 9 views
5

Właśnie zauważyłem, żeDlaczego TObjectList <T>. Czy usunąć wolne obiekty?

var 
    ObjList : TObjectList <TMyObject>; 
... 
ObjList := TObjectList <TMyObject>.Create (True); 
ObjList.Add (TMyObject.Create); 
ObjList.Clear; 

nie zwalnia obiekt. Patrząc na kod źródłowy wydaje się, że powiadomienie cnRemoved nie jest wywoływane w Clear (odziedziczone po TList <T>).

Moje pytanie: Czy jest to zamierzone? Czy jest jakiś powód, dla którego nie chcesz otrzymywać tych powiadomień w przypadku Clear? Czy może to być uznane za błąd w klasach kolekcji?

EDIT

Okazuje się, że mogę umieścić linię

inherited Create; 

na szczycie TMyObject destructor, który miał udać się do konstruktora. Dlatego mam zgłoszone wycieki pamięci, które wyglądały tak, jakby TObjectList nie zwalniało elementów. I spojrzenie na źródło przekonało mnie (zostałem uwięziony przez właściwość Count). Mimo wszystko, dziękuję za twoją pomoc!

+1

Dziki przypuszczenie: Czy oznaczono 'TMyObject.Destroy' jako' override'? –

+2

Jak mierzysz, że obiekt nie zostanie uwolniony? –

Odpowiedz

15

Lista zwalnia posiadane przedmioty, dzwoniąc pod numer .Clear. Masz błąd testowania. Próbka poniżej kod, napisany w Delphi XE, wyświetla to:

Calling CLEAR 
Object deleted. 
Object deleted. 
After CLEAR. Press ENTER to free L and Exit. 

Kod w TList<T>.Clear jest mylące, ponieważ Count jest rzeczywiście własnością. Spójrz na SetCount(), a następnie spójrz na DeleteRange(), a zobaczysz kod dla Notify(oldItems[i], cnRemoved) na końcu procedury DeleteRange.


program Project3; 

{$APPTYPE CONSOLE} 

uses SysUtils, Generics.Collections; 

type 
    TDelObject = class 
    public 
    destructor Destroy;override; 
    end; 

{ TDelObject } 

destructor TDelObject.Destroy; 
begin 
    WriteLn('Object deleted.'); 
    inherited; 
end; 

var L:TObjectList<TDelObject>; 

begin 
    L := TObjectList<TDelObject>.Create(True); 
    L.Add(TDelObject.Create); 
    L.Add(TDelObject.Create); 
    WriteLn('Calling CLEAR'); 
    L.Clear; 
    WriteLn('After CLEAR. Press ENTER to free L and Exit.'); 
    Readln; 
    L.Free; 
end. 
8

TList<T>.Clear rozmowy DeleteRange do pracy. Ostatnia część DeleteRange przebiega wokół wszystkich elementów wywołujących Notify przekazujących cnRemoved.

Twoja analiza kodu jest zatem niepoprawna. Powiadomienie o cnRemoved jest należycie dostarczone, a posiadane obiekty są zwalniane.

+2

Ehh. Cytuj z mojej odpowiedzi, 33 minut wcześniej na twoje: '" Kod w TList .Clear jest oszukańcza, ponieważ Count jest w rzeczywistości własnością .Spójrz na SetCount(), następnie spójrz na DeleteRange(), a zobaczysz kod dla Powiadom (oldItems [i], cnRemoved) na końcu procedury DeleteRange. "' –

+1

@Cosmin Wiem. Ale twoja odpowiedź zawiera mnóstwo kodu, który podkręca tę wiadomość. Jak wiesz, lubię zwięzłe odpowiedzi. –

+0

Twoja logika jest dobra, a twoja odpowiedź jest poprawna, ale ja wolę odpowiedź Cosmin, ponieważ ma przykładowy kod. Niemniej jednak daję +1 w obu przypadkach. –

Powiązane problemy