Fórum Como ocorre o quot;Destroyquot; de um TStringList em uma f #297865

30/09/2005

0

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


Paulo-serra

Paulo-serra

Responder

Posts

30/09/2005

Michelli88

Bom... eu sempre destruo o que eu crio manualmente.


Responder

Gostei + 0

30/09/2005

Paulo-serra

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.


Responder

Gostei + 0

30/09/2005

Michelli88

Coloca no Destroy!

Eu faço assim:
public
  destructor Destroy; override;
  List: StringList;

destructor TForm.Destroy;
begin
  List.Free;
end;



Responder

Gostei + 0

30/09/2005

Michelli88

Acho q nesse caso nao precisa dessa linha:

 List := TStringList.Create(); 


O Delphi cria e ele mesmo destroi;


Responder

Gostei + 0

30/09/2005

Paulo-serra

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.


Responder

Gostei + 0

30/09/2005

Michelli88

[b:70cc15de14]acho q isso aqui resolve seu problema´![/b:70cc15de14]

Function TFrmRelatorioTipoPagamento.RetornaStringList: TStringList;
Begin
    Result.Add(´Primeira linha da minha lista´);
End;



Responder

Gostei + 0

30/09/2005

Michael

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:

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


Responder

Gostei + 0

30/09/2005

Michael

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:

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


Responder

Gostei + 0

30/09/2005

Michelli88

É Verdade Michael, eu coloquei aquele exemplo, mas com variavel publica.

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;



Responder

Gostei + 0

30/09/2005

Siam

É 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.


Responder

Gostei + 0

30/09/2005

Michael

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].

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


Responder

Gostei + 0

30/09/2005

Michelli88

[b:8023b61035]eh... eu tentei fazer isso, mas nao sabia q tinha qdar o create pra funcionar heheheh valeu![/b:8023b61035]


Responder

Gostei + 0

30/09/2005

Massuda

Com relação a atribuir as strings ao memo, eu acho que o correto seria fazer...
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);



Responder

Gostei + 0

30/09/2005

Siam

Não seria assim:
function RetornaStringList(): TStringList; 
begin 
  Result := TStringList.Create; 
  Result.Add(´Primeira linha da lista´); 
end;
Para liberar:
procedure TForm1.BitBtn1Click(Sender: TObject); 
var L:TStringList;
begin 
  L := RetornaStringList; 
  Memo1.Lines.Assign(L); 
  L.Free;
end;



Responder

Gostei + 0

30/09/2005

Paulo-serra

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.


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar