Salve a tutti!
Mi spiego! Ho un semplice programma in cui sto testando l'uso di TStringList in una Function, e ho attivato la funzione del compilatore per testare le perdite di memoria con heaptrc.
Se io creo una funzione del tipo:
function TForm1.Prova: TStringList;
begin
result:=TStringList.Create;
with result do
begin
Add('Prova1');
add('Prova2');
Add('Prova3');
end;
end;
Poi con un pulsante verifico la funzione in un memo:
procedure TForm1.Button4Click(Sender: TObject);
begin
m1.Lines.AddStrings(Prova);
Prova.Free;
end;
1) Prova.Free è necessario? oppure la memoria viene liberata dal proprietario, cioè Form1
2) Sia con che senza Prova.Free i risultati sono quelli attesi, la applicazione si chiude senza errori, ma heaptrc mi segnala che ci sono 2 blocchi di memoria non liberati!!
N.B. Ovviamente non premendo il pulsante la applicazione si chiude senza perdite di memoria!
Chi mi spiega dove sbaglio?
grazie
Andrea
1) Prova.Free è necessario? oppure la memoria viene liberata dal proprietario, cioè Form1
No, perchè è un oggetto che crei te ed è slegato da Form1. Inoltre se il tuo intento è quello di liberare la memoria di Prova è sbagliato. Infatti seguendo il tuo codice, tu crei due TStringList.
m1.Lines.AddStrings(Prova);
La funzione Prova restituisce il primo TStringList creato e lo da come parametro al AddStrings, cosi aggiunge le stringhe al memo.
Invece questo codice crei il secondo TStringList, ma lo liberi subito. Praticamente fai eseguire al programma un lavoro completamente inutile (e sbagliato).
Perchè? Perchè nella funzione Prova gli hai detto di creare un TStringList e di restituirtelo come risultato. Quindi ogni volta che richiamerai Prova, creerai un TStringList.
Per rimediare, dovrai creare il primo TStringList, inserirlo in una variabile (cosi poterlo usare tranquillamente per fare quello che devi fare), aggiungerlo al memo e poi liberarlo (quando non ti servirà più). Come?
procedure TForm1.Button1Click(Sender: TObject);
var
sList: TStringList;
begin
sList := Prova;
m1.Lines.AddStrings(sList);
sList.Free;
end;
@AndreaM
un suggerimento
quando scrivi una procedure o una function che alloca risorse, dai un nome significativo (il tempo passa e non sempre ci si ricorda di come abbiamo scritto un programma nel passato), ad esempio, nel tuo caso:
function Tform1.CreateAndPopulateProva: TStringList;
in questo modo l'evento OnClick del bottone sarebbe stato:
procedure TForm1.Button4Click(Sender: TObject);
begin
m1.Lines.AddStrings(CreateAndPopulateProva);
CreateAndPopulateProva.Free;
end;
non cambia nulla ovviamente ma forse l'errore sarebbe stato più evidente ;)