Po pierwsze, nie twórz obiektów wewnątrz try
, a przed nim — jeśli kostruktor z jakiegoś powodu rzuci wyjątek, to blok finally wywali kolejny, bo wykona Free
na nieprawidłowej referencji. W przypadku TStringList
nie ma to większego znaczenia, ale konstruktor np. TFileStream
może rzucić wyjątkiem jeśli nie będzie pliku lub nie będzie miał do niego dostępu (wedle wskazanych flag).
Poprawna konstrukcja wygląda jak niżej, dla dowolnego typu tworzonej klasy:
Variable := TSomeClass.Create();
try
// do something
finally
Variable.Free();
end;
Po drugie, metoda TStringList.LoadFromFile
nie posiada wycieków pamięci, a sam menedżer zadań nie jest dobrym narzędziem do szukania problemów z pamięcią. Dobrym narzędziem za to jest moduł HeapTrc
, znajdujący się w bibliotece standardowej. Możesz go samodzielnie dopisać do listy uses
w głównym module projektu, a możesz też zaznaczyć jego użycie w oknie ustawień projektu.
Jeśli robisz program okienkowy, to istnienie modułu HeapTrc
w sekcji uses
spowoduje, że po zamknięciu programu zostanie wyświetlone okienko z podsumowaniem użycia pamięci. Jeśli program generuje wycieki, to po zamknięciu programu wyskoczy wiele okien, jedno po drugim i każde z osobna będzie pokazywać jakiś fragment logu. Dlatego lepszym sposobem jest uruchomienie programu z poziomu konsoli — wtedy cały log zostanie wyświetlony w konsoli.
Jest to o tyle eleganckie rozwiązanie, że w logu są szczegółowe informacje na temat tego ile pamięci wyciekło, a także w którym module i w której linijce jest alokowana pamięć, która później nigdy nie jest zwalniana. W ten sposób bardzo szybko można namierzyć alokacje do późniejszego zwolnienia.
Natomiast menedżer zadań może pokazywać większe zużycie pamięci po zwolnieniu listy niż przed jej utworzeniem, bo menedżer pamieci może zostawić pewne bloki pamięci ”na później”. Nie powinieneś się przejmować tym co robi menedżer pamięci, bo i tak nie masz na niego wpływu. Jeśli log generowany przez HeapTrc
nie pokazuje wycieków, to reszta nie ma znaczenia.