Risposta semplice (con esempi):
Quando si esegue
Risultato: = vStrList
si assegna vStrList ai risultati. In questo momento vStrList e Result SONO LA STESSA COSA! Quindi, nella prossima riga di codice, quando si libera vStrList, si libera anche Result (beh, questo non è TECNICO, ma l'ho usato per mantenere la spiegazione semplice). Questo è il motivo per cui si ottiene un AV quando si tenta di utilizzare il risultato della funzione. Il risultato è stato distrutto quando hai liberato vStrList.
Quindi, questo risolverà il problema:
function FuncStringList:TStringList;
begin
Result := TStringList.Create;
// Do stuff with Result
// never free (here, in this function) the Result
end;
Il chiamante di FuncStringList dovrà liberare "Risultato".
si chiamano in questo modo:
myStringList := FuncStringList;
try
myStringList.Items.Count
finally
freeandnil(myStringList); <------------- NOW you can free "Result"
end;
.
Un altro esempio:
function makelist: tstringlist;
begin
result := tstringlist.create;
result.add('1');
result.add('2');
end;
procedure TForm1.Button_GOOD_Click(Sender: TObject);
var list : tstringlist;
begin
list := makelist;
DoStuff(list);
list.free; //ok
end;
procedure TForm1.Button_BAD_Click(Sender: TObject);
begin
listbox1.items.Assign(makelist); // <---- memory leak here because you forgot to free
end;
ho messo questa nota qui prima che qualcuno avrà inizio 'raccogliere' sulla mia spiegazione. Nella mia spiegazione ho usato alcune "scorciatoie" per evitare che concetti complessi (come l'assegnazione del puntatore) mantengano le cose molto semplici. @gath ha posto una domanda di base che significa che sta ancora imparando le basi della programmazione.
Attenzione. Poiché le variabili allocate nello stack non sono inizializzate su 0, e assegnate() controlla solo per <> nil, non riuscendo a crearlo prima di chiamare la funzione * non * attiverà l'asserzione. –
Buona presa, Mason. Lo correggerò nel mio post. –