Como ocorre o quot;Destroyquot; de um TStringList em uma f
Vai aí uma espécie de QUIZ para nossos amigos.
É 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
É 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
Curtidas 0
Respostas
Michelli88
30/09/2005
Bom... eu sempre destruo o que eu crio manualmente.
GOSTEI 0
Paulo-serra
30/09/2005
Eu tentei destruir da seguinte forma:
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.
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
Michelli88
30/09/2005
Coloca no Destroy!
Eu faço assim:
Eu faço assim:
public destructor Destroy; override; List: StringList; destructor TForm.Destroy; begin List.Free; end;
GOSTEI 0
Michelli88
30/09/2005
Acho q nesse caso nao precisa dessa linha:
O Delphi cria e ele mesmo destroi;
List := TStringList.Create();
O Delphi cria e ele mesmo destroi;
GOSTEI 0
Paulo-serra
30/09/2005
Mas a variável Lista é uma variável local dentro da minha função e não uma variável pública do meu Form.
GOSTEI 0
Michelli88
30/09/2005
[b:70cc15de14]acho q isso aqui resolve seu problema´![/b:70cc15de14]
Function TFrmRelatorioTipoPagamento.RetornaStringList: TStringList; Begin Result.Add(´Primeira linha da minha lista´); End;
GOSTEI 0
Michael
30/09/2005
Olá colega!
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:
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:
E use-a assim:
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
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 Delphi cria e ele mesmo destroi;
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
Michael
30/09/2005
Uma segunda dica: vc não precisa de uma variável auxiliar dentro da função. Como Result é sempre do tipo do retorno da função, vc pode usá-la diretamente para operações. Veja:
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
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
Michelli88
30/09/2005
É Verdade Michael, eu coloquei aquele exemplo, mas com variavel publica.
Bom, eu corrigi aquele codigo q eu postei errado.
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
Siam
30/09/2005
É Verdade Michael, eu coloquei aquele exemplo, mas com variavel publica.
Bom, eu corrigi aquele codigo q eu postei errado.
Código:
Function TFrmRelatorioTipoPagamento.RetornaStringList: TStringList;
var
lista: TStringList;
Begin
lista.Add(´Primeira linha da minha lista´);
Result:=Lista;
End;
Acho que continua errado.GOSTEI 0
Michael
30/09/2005
Olá Michelli!
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].
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
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
Michelli88
30/09/2005
[b:8023b61035]eh... eu tentei fazer isso, mas nao sabia q tinha qdar o create pra funcionar heheheh valeu![/b:8023b61035]
GOSTEI 0
Massuda
30/09/2005
Com relação a atribuir as strings ao memo, eu acho que o correto seria fazer...
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 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
Siam
30/09/2005
Não seria assim:Para liberar:
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
Paulo-serra
30/09/2005
Acabei seguindo o conselho do Michael e colocando como resultado da minha função a propriedade Text do meu StringList, em vez do próprio StringList.
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.
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