Neste post vamos abordar um pouco sobre a utilização dos métodos destrutores, que são o:

  • Release: utiliza somente em forms, pois é introduzido na classe TCustomForm
  • Free: que é um destrutor da classe TObject do Object Pascal;
  •  FreeAndNil: este último é uma procedure.

O Relese deve ser usado se você quer liberar um form de dentro dele mesmo, por exemplo, no evento OnClick de um botão no próprio form. O Release posta uma mensagem CM_RELEASE para o form (veja TCustomForm.Release na unit Forms), que quando processada, dispara o Free. A diferença é que o Release processa todas as mensagens e eventos que estiverem na fila do form antes que ele seja destruido. Disparar um Free de dentro do form, pode gerar um AV(Acess Violation).

O Free deve ser usado quando você quer libera o form fora do contexto do form, por exemplo, isto está correto:

Ex:.
var
  Form
begin
  Form:= TForm1.Create(Application);
  Form.ShowModal;
  Form.Free;
end;

Usar o Release de fora do form também gera o mesmo resultado, porém de forma menos otimizada, pois a mensagem é postada para o form que depois chama o Free.

Ex:.
var
  Form
begin
  Form := TForm1.Create(Application);
  Form.ShowModal;
  Form.Release;
end;

O FreeAndNil é apenas uma procedure que atribui nil a variável de instância e na sequência chama um Free, conforme se pode ver no seu código ultra-simples em SysUtils:

procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;

Ele só é interessante de ser usado quando você precisa testar se o objeto está instanciado usando o Assigned. Se você chama apenas o Free a memória é liberada da mesma forma, sem vestígios, porém, se a variável não for reutilizada e ainda estiver dentro do escopo, continuará apontando para um endereço inválido. Isso não consome mais memória, e isso não é um problema se você não precisa mais da variável. Por isso aconselho sempre a usar variáveis com o menor escopo possível, pois dessa forma, você quase nunca precisa se preocupar com esse tipo de problema.

Exemplo 1: Variável implicita:

procedure TForm1.Button5Click(Sender: TObject);
begin
  with TForm2.Create(nil) do
  try
    ShowModal;
  finally
    Free;
  end;
end;

Neste caso você nem precisa se preocupar com variável nenhuma. Sei que muita gente odeia o with, mas em pequenos trechos como esse, não vejo desvantagens, e ele ainda me economiza a declaração da variável para o form. Não preciso usar Release pois estou liberando o form fora dele, e não preciso do FreeAndNil porque em nenhum momento preciso testar variável nenhuma para saber se existe uma instância.

Exemplo 2: Variável local:

procedure TForm1.Button4Click(Sender: TObject);
var
  Form: TForm2;
begin
  Form:= TForm2.Create(Application);
  Form.ShowModal;
  Form.Free;
end;

O resultado é o mesmo do exemplo 1, porém usando uma variável local. Não precisamos do Release pelo mesmo motivo do anterior e não precisamos do FreeAndNil, pois ao final da procedure, a variável Form sai do escopo e morre. Não precisamos nos preocupar em atribuir nil a ela.

É isto aí galera da Devmedia.

Abraço e até a próxima!!