Fórum Problema ao atribuir a variaveis objetos instanciados #336082

12/01/2007

0

Preciso dar um free num componente que está numa form, e atribuir à ele um outro objeto do mesmo tipo que foi instanciado manualmente.

O seguinte teste não deu certo: suponhamos que eu tenho um componente A na form instanciado, que nada mais é que uma variável do tipo A que aponta para esse objeto. E tenho um Componente do mesmo tipo chamado B e referenciado por B. Quero trocar, quero que A (referencia ou variavel) aponte pra B, e B continue apontando pra B, para que o objeto a possa ser liberado da memoria. Pra isso eu uso uma variavel não instanciada do mesmo tipo chamada C.

Se eu faço C:=A;
A:=B;
C.free;

O que deveria acontecer? A apontando pra B, sendo A e B a mesma coisa e o objeto instanciado na memoria A não existir mais, sendo C = nil;

Não é isso que está acontecendo, por favor, alguém poderia olhar meu código?

procedure TForm1.Button1Click(Sender: TObject);
var
  dummyEdit: Tedit;
begin

  dummyEdit := Edit1;

  Edit1 := Edit2;

  {Mostra os nomes e conteudos dos edits. Nesse ponto, o dummy aponta para o
  edit1, ele É o edit 1 (o objeto instanciado), enquanto que o edit1
  (variavel) aponta para o objeto edit 2, ele É o edit 2}

  ShowMessage(´Nome: ´ + dummyEdit.Name + ´ Conteudo: ´ + dummyEdit.Text);
  ShowMessage(´Nome: ´ + Edit1.Name + ´ Conteudo: ´ + Edit1.Text);
  ShowMessage(´Nome: ´ + Edit2.Name + ´ Conteudo: ´ + Edit2.Text);


  {porque diabos essa linha abaixo não funciona direito? ela está liberando da
   memoriao edit 1, que está sendo apontado pelo dummyedit, mas a variavel edit1
   perde sua referencia ao edit 2 e volta a apontar para o edit1,
   que já foi dado free}

  dummyEdit.Free;

  ShowMessage(´Nome: ´ + dummyEdit.Name + ´ Conteudo: ´ + dummyEdit.Text);
  //A linha abaixo dá access violation, prque o edit1 não aponta mais para o edit2?
  ShowMessage(´Nome: ´ + Edit1.Name + ´ Conteudo: ´ + Edit1.Text);
  ShowMessage(´Nome: ´ + Edit2.Name + ´ Conteudo: ´ + Edit2.Text);

  Edit1 := Edit2;

  {Se eu fizer a referencia novamente, ele funciona como eu quero}

  ShowMessage(´Nome: ´ + dummyEdit.Name + ´ Conteudo: ´ + dummyEdit.Text);
  ShowMessage(´Nome: ´ + Edit1.Name + ´ Conteudo: ´ + Edit1.Text);
  ShowMessage(´Nome: ´ + Edit2.Name + ´ Conteudo: ´ + Edit2.Text);
end;



Obrigado!


Vitor Rubio

Vitor Rubio

Responder

Posts

12/01/2007

Emerson Nascimento

quando você faz dummyEdit.Free você está liberando na verdade o Edit1 (pois o dummyEdit é o próprio objeto Edit1).

procedure TForm1.Button1Click(Sender: TObject);
var
  dummyEdit: Tedit;
begin

  dummyEdit := Edit1;

  Edit1 := Edit2;

  {Mostra os nomes e conteudos dos edits. Nesse ponto, o dummy aponta para o
  edit1, ele É o edit 1 (o objeto instanciado), enquanto que o edit1
  (variavel) aponta para o objeto edit 2, ele É o edit 2}

  ShowMessage(´Nome: ´ + dummyEdit.Name + ´ Conteudo: ´ + dummyEdit.Text);
  ShowMessage(´Nome: ´ + Edit1.Name + ´ Conteudo: ´ + Edit1.Text);
  ShowMessage(´Nome: ´ + Edit2.Name + ´ Conteudo: ´ + Edit2.Text);


  {porque diabos essa linha abaixo não funciona direito? ela está liberando da
   memoriao edit 1, que está sendo apontado pelo dummyedit, mas a variavel edit1
   perde sua referencia ao edit 2 e volta a apontar para o edit1,
   que já foi dado free}

  dummyEdit.Free;

  ShowMessage(´Nome: ´ + dummyEdit.Name + ´ Conteudo: ´ + dummyEdit.Text);
  // A linha abaixo dá access violation, prque o edit1 não aponta mais para o edit2?
O Edit1 não aponta mais para o Edit2, porque o Edit1 não existe mais! Ele foi
apagado da memória pelo comando dummyEdit.Free, portando ele não aponta mais
para lugar nenhum
  ShowMessage(´Nome: ´ + Edit1.Name + ´ Conteudo: ´ + Edit1.Text);
  ShowMessage(´Nome: ´ + Edit2.Name + ´ Conteudo: ´ + Edit2.Text);

  Edit1 := Edit2;

  {Se eu fizer a referencia novamente, ele funciona como eu quero}
é óbvio! é o mesmo que você fez com o dummyEdit. tente exibir
algo do dummyEdit antes do comando dummyEdit := Edit1;
não funcionaria porque dummyEdit não existiria na memória;
ele passa a existir quando você o aponta para Edit1, da mesma
forma que o Edit1 - depois de apagado - passa a existir
novamente depois que você o aponta para Edit2
  ShowMessage(´Nome: ´ + dummyEdit.Name + ´ Conteudo: ´ + dummyEdit.Text);
  ShowMessage(´Nome: ´ + Edit1.Name + ´ Conteudo: ´ + Edit1.Text);
  ShowMessage(´Nome: ´ + Edit2.Name + ´ Conteudo: ´ + Edit2.Text);
end;



Responder

Gostei + 0

12/01/2007

Vitor Rubio

So que, por exemplo, o Objeto Edit1 não é algo diferente da variável Edit1?

Se eu tenho edit1 e edit2 na minha form, lá em cima, antes do private eu tenho as variaveis edit1, que aponta para o objeto instanciado edit1 e o edit2, que aponta para o edit2 respectivamente.

A variavel edit1 não poderia apontar para qualquer outro edit instanciado que não fosse o edit1? Na teoria sim. Foi isso que eu tentei fazer, atribuir o ponteiro do edit2 ao edit1, só que se eu fizesse isso, o objeto instanciado na memoria edit1 ficaria perdido sem quem o liberasse.

por isso e criei a variavel dummy, para apontar para o mesmo edit que o edit1, para que quando o edit1 passasse a apontar para o edit2, eu pudesse limpar o edit1 da memoria usando a variavel dummy.

Não deu certo. Com outras classes que não fossem componentes daria certo... Ao liberar o dummy, a variavel edit1 para de apontar para o edit2 como estava antes e começa a apontar para o nada, como se ainda quisesse apontar para o edit1 que foi liberado.

Olha essa parte do código depois de dar dummy.free:

ShowMessage(´Nome: ´ + dummyEdit.Name + ´ Conteudo: ´ + dummyEdit.Text);  //não deveria permitir, já que eu liberei dummy, devia dar access violation
  ShowMessage(´Nome: ´ + Edit1.Name + ´ Conteudo: ´ + Edit1.Text);
  ShowMessage(´Nome: ´ + Edit2.Name + ´ Conteudo: ´ + Edit2.Text);


Eu liberei dummy, então deveria dar access violation, mas não deu.

Olha esse outro código, que faz a mesmissima coisa que o anterior, mas usando uma outra classe que não seja componente:

 Tmensagem = class
  public
    mensagem: string;
    destructor destroy; override;
  end;


destructor Tmensagem.destroy;
begin
  mensagem := ´´;
  inherited;
end;


procedure TForm1.Button2Click(Sender: TObject);
var
  mensagem1, mensagem2, mensagemdummy: Tmensagem;
begin
  //criando os objetos
  mensagem1 := Tmensagem.Create;
  mensagem2 := Tmensagem.Create;
  mensagem1.mensagem := ´Aqui jaz Mensagem 1´;
  mensagem2.mensagem := ´Aqui jaz Mensagem 2´;


  ShowMessage(´Logo depois de criar:´);
  //ShowMessage(´MensagemDummy: ´ + mensagemdummy.mensagem); //essa não pode, obvio
  ShowMessage(´Mensagem 1: ´ + mensagem1.mensagem);
  ShowMessage(´Mensagem 2: ´ + mensagem2.mensagem);

  mensagemdummy := mensagem1;
  mensagem1 := mensagem2;

  ShowMessage(´Assim que atribuir:´);
  ShowMessage(´MensagemDummy: ´ + mensagemdummy.mensagem);
  ShowMessage(´Mensagem 1: ´ + mensagem1.mensagem);
  ShowMessage(´Mensagem 2: ´ + mensagem2.mensagem);

  mensagemdummy.Free;

  ShowMessage(´Depois de liberar dummy´);
  //ShowMessage(´MensagemDummy: ´ + mensagemdummy.mensagem); //obvio que não pode
  ShowMessage(´Mensagem 1: ´ + mensagem1.mensagem);
  ShowMessage(´Mensagem 2: ´ + mensagem2.mensagem);

end;



Responder

Gostei + 0

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

Aceitar