Tutaj następujący wiersz przydziela nowy BSTR
i wypełnia jego wskaźnik do wskaźnika SL.Objects[]
.
SL.AddObject('my string', TObject(SysAllocString(PWideChar(WS))));
Więc po będzie ostatecznie wyciek pamięci:
var
WS: WideString;
begin
WS := PWideChar(SL.Objects[0]);
Tutaj nowy WS instancja zostanie rozdzielona, więc instancja BSTR wskazanych przez SL.Objects[0]
nie zostanie zwolniony.
I dodaje pracuje przez przypadek:
SL.AddObject('my string', TObject(PWideChar(WS)));
pamięci wskazywanej przez bufor pamięci jest nadal PWideChar(WS)
zawierające do poprzedniego WS: WideString
instancji. Tak więc może działać ... dopóki bufor nie zostanie ponownie użyty i nadpisany przez inne dane, a inny tekst zostanie zwrócony lub wystąpi losowy GPF.
Za radą: nigdy nie oszukuj systemu typu Delphi, przechowując coś innego niż TObject
w zmiennej wpisanej jako TObject
... chyba że wiesz, co robisz. Nie baw się wskazówkami, dopóki nie wiesz, czym one są i jak działają.
Nie widzę żadnej korzyści z przechowywania WideString
w obrębie wpisu !Zmień strukturę danych: stwórz prawdziwy class
, przechowując swój ciąg. Wtedy wszystko będzie jasne i czyste:
type
TMyStoreWS = class
protected
fText: WideString;
public
constructor Create(const aText: WideString); virtual;
property Text: WideString read fText write fText;
end;
constructor TMyStoreWS.Create(const aText: WideString);
begin
inherited Create;
fText := aText;
end;
...
SL.AddObject('my string', TMyStoreWS.Create(aText)); // clean
...
ShowMessage(SL.Objects[0].Text); // clean
SL.Objects[0].Free; // don't forget to release
Mała narzut alokacji instancji class
jest negligeable w odniesieniu do BSTR
alokacji strun, mogę ci powiedzieć. Twój kod byłby zdecydowanie czystszy i łatwiejszy do utrzymania/ewolucji.
Miałem nadzieję, że pozwolę systemowi zarządzać zniszczeniem "obiektu" WideString. jeśli używam struktury klasy, muszę ręcznie zwolnić każdy obiekt (nie ma OwnsObject w D7 dla TStringList). Nadal nie jestem pewien, czy ** musi ** wolne ciągi, które są przydzielone z 'SysAllocString' lub system może zająć się tym dla mnie? ... – zig
Tak, ** musisz ** darmowe ciągi BSTR przydzielone przez SysAllocString. –