Fórum Como ocorre o quot;Destroyquot; de um TStringList em uma f #297865
30/09/2005
0
É o seguinte:
Tenho uma função chamada RetornaStringList() que está implementada da seguinte maneira:
Function RetornaStringList(): TStringList;
Var
lista: TStrings;
Begin
Lista := TStringList.Create();
Lista.Add(´Primeira linha da lista´);
Result := (Formula as TStringList);
end;
E executo a chamada à função da seguinte maneira:
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
memo1.Lines := RetornaStringList;
end;
A dúvida é: Após ser executado o Result da função RetornaStringList, como é feita a liberação da memória ocupada pela variável Lista (do Tipo StringList). Ela só ocupará memória durante ´sua existência´ no escopo da função e depois é automaticamente destruída ou terei que destruí-la manualmente ?
Paulo Serra
Paulo-serra
Curtir tópico
+ 0Posts
30/09/2005
Michelli88
Gostei + 0
30/09/2005
Paulo-serra
Function RetornaStringList(): TStringList;
Var
Lista: TStrings;
Begin
Try
List := TStringList.Create();
Lista.Add(´Primeira linha da minha lista´);
Result := (Lista as TStringList);
Finally
Lista.Free;
End;
end;
Mas quando fui executar a função:
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
memo.Lines := RetornaStringList;
end;
Recebi um erro de Access Violation, como se o Result da Função já tivesse destruído a variável Lista antes de ´jogar´ o resultado no meu memo.
Gostei + 0
30/09/2005
Michelli88
Eu faço assim:
public destructor Destroy; override; List: StringList; destructor TForm.Destroy; begin List.Free; end;
Gostei + 0
30/09/2005
Michelli88
List := TStringList.Create();
O Delphi cria e ele mesmo destroi;
Gostei + 0
30/09/2005
Paulo-serra
Gostei + 0
30/09/2005
Michelli88
Function TFrmRelatorioTipoPagamento.RetornaStringList: TStringList; Begin Result.Add(´Primeira linha da minha lista´); End;
Gostei + 0
30/09/2005
Michael
Vc [b:7ef1c344f5]não[/b:7ef1c344f5] pode liberar Lista da memória. Quando vc atribui um objeto a outro, o que ocorre, na verdade, não é a cópia de todos os campos e propriedades de um para o outro, e sim apenas a [b:7ef1c344f5]referência[/b:7ef1c344f5] na memória. Ou seja, ao dizer:
memo1.Lines := RetornaStringList;
Vc está fazendo [b:7ef1c344f5]Lines [/b:7ef1c344f5]apontar para o retorno da função na memória.
No seu caso, por ser uma função simples, vc pode fazer o seguinte: mude sua função para retornar uma string, e atribua a Result a propriedade Text de Lista:
Result := Lista.Text;
E use-a assim:
Memo1.Lines.Text := RetornaStringList;
Seria legal mudar o nome da função tbm para algo mais pertinente ao contexto.
O [b:7ef1c344f5]form [/b:7ef1c344f5]automaticamente libera da memória apenas os componentes criados em design-time ou os objetos que foram criados passando via construtor Create ele, o form, como [b:7ef1c344f5]Owner[/b:7ef1c344f5]. Como a classe TStrings não possue nenhum parâmetro no construtor, isso não pode ser aplicado a ela.
A afirmação do Paulo está correta: a variável Lista existe apenas dentro do escopo da função. Sua ´vida´ não se extende além dos domínios da função.
[]´s
Gostei + 0
30/09/2005
Michael
function RetornaStringList: TStringList; begin Result := TStringList.Create; Result.Add(´Primeira linha da minha lista´); end;
Acho q assim fica mais fácil de ver pq não se pode dar um [b:13c39cd322]Free [/b:13c39cd322]em [b:13c39cd322]Result[/b:13c39cd322].
[]´s
Gostei + 0
30/09/2005
Michelli88
Bom, eu corrigi aquele codigo q eu postei errado.
Function TFrmRelatorioTipoPagamento.RetornaStringList: TStringList; var lista: TStringList; Begin lista.Add(´Primeira linha da minha lista´); Result:=Lista; End;
Gostei + 0
30/09/2005
Siam
Gostei + 0
30/09/2005
Michael
Usando a variável Lista ou Result diretamente, é necessário instanciar o objeto na memória, usando o construtor de TStrings/TStringList. Sem isso irá ocorrer um erro de [b:792bb4d660]Access Violation[/b:792bb4d660].
Function TFrmRelatorioTipoPagamento.RetornaStringList: TStringList; var lista: TStringList; Begin Lista := TStringList.Create; Lista.Add(´Primeira linha da minha lista´); Result := Lista; End;
Aproveitando a deixa, eu friso que é melhor usar Result diretamente, pois o consumo de recursos é o mínimo possível. Embora não seja ´visível´, em toda função [b:792bb4d660]Result [/b:792bb4d660]é declarado como o tipo de retorno da função. Portanto, usando uma variável auxiliar, estaremos duplicando a quantidade de memória utilizada.
[]´s
Gostei + 0
30/09/2005
Michelli88
Gostei + 0
30/09/2005
Massuda
procedure TForm1.BitBtn1Click(Sender: TObject); var Lista: TStringList; begin Lista := RetornaStringList; memo1.Lines.AddStrings(Lista); Lista.Free; end;
Do jeito que você está fazendo a lista de strings usada internamente pelo memo está sendo substituída pela lista que sua função criou e essa lista está sendo deixada para trás na memória.
Pessoalmente, para popular listas de strings, eu prefiro fazer uma procedure que recebe como parametros um TStrings...
procedure PopularLista(Lista: TStrings); begin Lista.Add(´1´); end; // exemplo de uso // PopularLista(Memo1.Lines);
Gostei + 0
30/09/2005
Siam
function RetornaStringList(): TStringList; begin Result := TStringList.Create; Result.Add(´Primeira linha da lista´); end;
procedure TForm1.BitBtn1Click(Sender: TObject); var L:TStringList; begin L := RetornaStringList; Memo1.Lines.Assign(L); L.Free; end;
Gostei + 0
30/09/2005
Paulo-serra
Realmente não estava atentando que um StringList só recebe a referência de outro.
Outra dica importante que vou passar a utilizar agora é utilizar o próprio Result em vez de criar uma variável Local na função. Pode ser algo básico, mas eu realmente não sabia.
Valeu mesmo Michael.
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)