Destruir instancia da memoria

Delphi

21/07/2006

Amigo se puderem ajudar eu agradeço, já fiz de tudo, mas nada, o que esta contecendo e que quanto mais eu executo a função abaixo mais memoria ele consome, gereando um grande erro de memory leak, será que alguem pode me ajudar...


Function RerImagem: Tbitmap;
Var
Tb: TBitmap;
begin
  Tb:= TBitmap.Create;
       try
       Tb.Width := 700;
       Tb.Height:= 500;
       ct.BufferedDisplay:=False;
       ct.Draw(Tb.Canvas,Rect(0, 0, 700, 500));
       ct.BufferedDisplay:=True;
       Result:= Tb;
       finally
//       FreeAndNil(Tb); se habilitar aqui não retorna a imagem
       end;
end;


helllppppp.....


Sremulador

Sremulador

Curtidas 0

Respostas

Massuda

Massuda

21/07/2006

Do jeito que sua função foi escrita, você deve destruir o bitmap criado pela função [b:4763525521]depois[/b:4763525521] de utilizar o bitmap, por exemplo...
var
  Bitmap: TBitmap;
...
  Bitmap := RerImagem;
  // faz alguma coisa com Bitmap
  Bitmap.Free;
...



GOSTEI 0
Marco Salles

Marco Salles

21/07/2006

[b:0f2429c6ed]Citação de massuda :[/b:0f2429c6ed]
Do jeito que sua função foi escrita, você deve destruir o bitmap criado pela função depois de utilizar o bitmap, por exemplo...Código: var Bitmap: TBitmap; ... Bitmap := RerImagem; // faz alguma coisa com Bitmap Bitmap.Free; ...



[b:0f2429c6ed]´Neste caso, sremulador , voce esta criando uma função que retornará uma nova instância de TBitmap . Portanto não é correto destruir o objeto referenciado por Tb no final da função, porque assim destruirá o próprio objeto que deveria ser retornado, devolvendo um ponteiro inválido que pode causar uma AccessViolation na primeira referência ao objeto na memória. entre outros erros´[/b:0f2429c6ed]


GOSTEI 0
Massuda

Massuda

21/07/2006

Marco, sua explicação está perfeita.


GOSTEI 0
Sremulador

Sremulador

21/07/2006

Neste caso, sremulador , voce esta criando uma função que retornará uma nova instância de TBitmap . Portanto não é correto destruir o objeto referenciado por Tb no final da função, porque assim destruirá o próprio objeto que deveria ser retornado, devolvendo um ponteiro inválido que pode causar uma AccessViolation na primeira referência ao objeto na memória. entre outros erros´


Concordo plenamente, mas como resolver esta broncad...


GOSTEI 0
Bruno Belchior

Bruno Belchior

21/07/2006

Ai é como o Massuda falou, o método que chamou essa função, fica com a responsabilidade de destruir esse objeto depois que seu uso não é mais necessário.


GOSTEI 0
Marco Salles

Marco Salles

21/07/2006

citação de marco salles
[quote:41443584b8]Citação de massuda : Citação: Do jeito que sua função foi escrita, [b:41443584b8]você deve destruir o bitmap criado pela função depois de utilizar o bitmap[/b:41443584b8], por exemplo...Código: var Bitmap: TBitmap; ... Bitmap := RerImagem; // faz alguma coisa com Bitmap [b:41443584b8]Bitmap.Free;[/b:41443584b8]

... [/quote:41443584b8]

em outras palavras:

citação de Bruno Belchior
Ai é como o Massuda falou, o método que chamou essa função, fica com a responsabilidade de destruir esse objeto depois que seu uso não é mais necessário.



GOSTEI 0
Sremulador

Sremulador

21/07/2006

hunnnn........., blz...


GOSTEI 0
Raserafim

Raserafim

21/07/2006

então não é preciso destruir nada? tudo o que foi criado dentro do procedimento vai ser destruido por ele?


GOSTEI 0
Michael

Michael

21/07/2006

Quando se cria um procedimento que deve devolver a instância de uma classe, é recomendado utilizar procedures ao invés de funções. A razão disso é justamente explicitar quem será o responsável por liberar a memória alocada, no momento oportuno. O código do colega [b:814d170aca]sremulador [/b:814d170aca]poderia ser re-escrito para:

procedure RerImagem(var Imagem: TBitmap);
begin
   Imagem.Width := 700;
   Imagem.Height:= 500;
   ct.BufferedDisplay:=False;
   ct.Draw(Imagem.Canvas,Rect(0, 0, 700, 500));
   ct.BufferedDisplay:=True;
end;


E, no local da chamada a esta procedure:

var
  Imagem: TBitmap;
begin
  Imagem := TBitmap.Create;
  try
    RetImagem(Imagem);
    // Faz alguma coisa com Imagem
  finally
    Imagem.Free;
  end;
end;


Via de regra quem cria um objeto deve destruí-lo - excetuando-se componentes, que podem ter um [b:814d170aca]Owner [/b:814d170aca]para fazer isso. Se uma função retorna uma instância de uma classe, então esta responsabilidade está sendo repassada para o seu chamador, e isso muitas vezes não fica claro, o que pode levar a memory leaks na aplicação.

então não é preciso destruir nada? tudo o que foi criado dentro do procedimento vai ser destruido por ele?

Negativo. No Delphi a única forma de se ´automatizar´ a desalocação de memória de objetos é utilizando-se o mecanismo de Owner, que funciona apenas com componentes. Ou através de [b:814d170aca]interfaces[/b:814d170aca], que possuem [b:814d170aca]Reference Count[/b:814d170aca]. No mais é o programador quem deve se preocupar em liberar a memória utilizada.
Em ambientes gerenciados, como o .NET e Java, a desalocação de memória é feita pela própria plataforma, através do [b:814d170aca]Garbage Collecto[/b:814d170aca]r. Desta forma não é necessário explicitamente destruir objetos, pois isso será feito automaticamente assim que eles perderem referência (RefCount = 0).

Para quem ainda tem alguma dúvida sobre criação e destruição de objetos e componentes em run-time, eu sugiro a leituro do meu artigo sobre o assunto, publicado na edição 72 da revista ClubeDelphi.

[]´s


GOSTEI 0
Siam

Siam

21/07/2006

Pelo que ví, a função original RerImage deveria retornar um TBitmap mas não está retornando nada.


GOSTEI 0
Marco Salles

Marco Salles

21/07/2006

[b:a162055b0c]Quando se cria um procedimento que deve devolver a instância de uma classe, é recomendado utilizar procedures ao invés de funções. [/b:a162055b0c]

[b:a162055b0c]Falou Tudo...[/b:a162055b0c]


GOSTEI 0
Siam

Siam

21/07/2006

[quote:6c2f900232=´Marco Salles´]Quando se cria um procedimento que deve devolver a instância de uma classe, é recomendado utilizar procedures ao invés de funções.[/quote:6c2f900232]Porquê ?


GOSTEI 0
Marco Salles

Marco Salles

21/07/2006

Qeum fez a colocação foi o [b:b2c47def40]Michael[/b:b2c47def40]

[b:b2c47def40]Michael[/b:b2c47def40] escreveu: Quando se cria um procedimento que deve devolver a instância de uma classe, é recomendado utilizar procedures ao invés de funções. Porquê ?


:arrow:
A razão disso é justamente explicitar quem será o responsável por liberar a memória alocada, no momento oportuno.


Olha o parametro [b:b2c47def40]Var[/b:b2c47def40] no esboço da procedure

[b:b2c47def40]procedure RerImagem(var Imagem: TBitmap); [/b:b2c47def40]

ao inves disso:

[b:b2c47def40]Function RerImagem: Tbitmap; [/b:b2c47def40]


GOSTEI 0
Siam

Siam

21/07/2006

Tenho várias funções que retornam objetos e nunca tive problemas.
Gostaria que fosse fundamentada essa teoria pq até então acho que vai da maneira de cada um programar.


GOSTEI 0
Marco Salles

Marco Salles

21/07/2006

Tenho várias funções que retornam objetos e nunca tive problemas. Gostaria que fosse fundamentada essa teoria pq até então acho que vai da maneira de cada um programar.


Se voce usa funçoes e destroi o objeto referenciado no final da função no meu entendimento isto não esta correto...

Se o sremulador , não executasse seguidas veses o mesmo codigo , não iria perceber nenhuma anormalidade , passando por despercebido , algo conceitualmente errado.

Foi dado aqui duas saídas para o problema.. Uma usando função

1)
quando se usa [b:d453a7f944]funçoes[/b:d453a7f944] , voce deve tomar o cuidado de não destruir o objeto no Final da função... Então quem deve destruir o Objeto é o Chamador. Porem , isto pode não ficar claro , com anota o micheus em seu paragrafo sobre o assunto

então esta responsabilidade está sendo repassada para o seu chamador, e isso muitas vezes não fica claro, o que pode levar a memory leaks na aplicação.


2)
Agora usando [b:d453a7f944]procedures[/b:d453a7f944] o codigo fica mais limpo pois quem cria um objeto deve destruí-lo....E na chamada voce deve passar usando o parametro [b:d453a7f944]Var[/b:d453a7f944]


GOSTEI 0
Siam

Siam

21/07/2006

Se voce usa funçoes e destroi o objeto referenciado no final da função no meu entendimento isto não esta correto...
Mas quando se cria uma função para retornar um objeto, pq alguém destruiria esse objeto no final da função ? Isso pra mim não faz sentido.

Agora, é claro que se vc cria uma função retornando um objeto e esse objeto for criado sem o Owner, vc tem que saber que deve liberá-lo após sua utilização.

Ainda não estou convencido que é melhor utilizar procedures ao invés de funções.


GOSTEI 0
Michael

Michael

21/07/2006

[quote:66d27ead2f=´marcos salles´]1)
quando se usa funçoes , voce deve tomar o cuidado de não destruir o objeto no Final da função... Então quem deve destruir o Objeto é o Chamador. Porem , isto pode não ficar claro , com anota o [b:66d27ead2f]micheus[/b:66d27ead2f] em seu paragrafo sobre o assunto[/quote:66d27ead2f]
Micheus não, [b:66d27ead2f]Michael[/b:66d27ead2f]. ;-)

Gostaria que fosse fundamentada essa teoria pq até então acho que vai da maneira de cada um programar.

Isso não é uma teoria, mas uma boa prática de programação. Siga-a se achar conveniente. Apenas por curiosidade, segue a tradução do primeiro tópico sobre gerenciamento de exceções do [url=http://www.econos.de/delphi/cs.html]Delphi 4 Developer´s Guide Coding Standards Document[/url]:
[quote:66d27ead2f=´Xavier Pacheco´]Uso de try..finally

Sempre que possível, cada alocação de memória deve ser coincidir com uma construção try...finally.

SomeClass2 := TSomeClass.Create;
try
{ do some code }
finally
SomeClass2.Free;
end;[/quote:66d27ead2f]
Como é sabido, isso não é possível de ser feito dentro de uma função que retorne um objeto.

Mas quando se cria uma função para retornar um objeto, pq alguém destruiria esse objeto no final da função ? Isso pra mim não faz sentido.

Como já dito acima, quando se cria um objeto, a estrutura de código que deve ser seguida é:

Objeto := TObjeto.Create;
try
  // Alguma coisa é feita com Objeto
finally
  Objeto.Free;
end;

A única exceção é se o objeto sendo criado for um componente [u:66d27ead2f]E[/u:66d27ead2f] possuam um [b:66d27ead2f]Owner[/b:66d27ead2f]. Então vc a função vai retorna apenas o ponteiro para a instância, mas quem vai destruí-la vai ser outro componente.
Se vc tem uma função que cria um objeto e não o destrói ao final do seu uso, então a estrutura acima está sendo quebrada e isso pode levar, como eu já comentei,a memory leaks na aplicação.

Agora, é claro que se vc cria uma função retornando um objeto e esse objeto for criado sem o Owner...

Apenas componentes têm Owner. Objetos não.

...vc tem que saber que deve liberá-lo após sua utilização

Quando se trabalha em equipe, um outro programador que usar uma função assim pode não saber como ela foi criada, e portanto não saberá se destrói ou não o objeto sendo retornado.

A VCL é um bom exemplo disso. A maioria das funções não retornam objetos. E nas que fazem a instância retornada é gerenciada internamente pela classe (neste caso a função seria um método), que a libera da memória no momento certo, sem repassar esta responsabilidade para o programador.

[]´s


GOSTEI 0
Siam

Siam

21/07/2006

Como disse, vai da maneira de cada um programar. De um modo geral, objetos criados devem ser liberados sejam em procedures ou funções.


GOSTEI 0
POSTAR