Assigned não funciona!

27/03/2008

0

Olá pessoal!

Estou com problemas relacionados ao Assigned do Delphi.
Tenho a seguinte o seguinte código:

[b:a3daaefe8c]procedure TForm1.Button4Click(Sender: TObject);
var
funcionario1:TFuncionario;
funcionario2:TFuncionario;
begin
funcionario1 := TFuncionario.create(self);
funcionario1.nome := ´João´;
funcionario2 := funcionario1; //passando por referência
edit1.text := funcionario2.nome;
FreeAndNil(funcionario1);
if Assigned(funcionario2) then //ainda aponta memória que funcionario1 ocupava.
FreeAndNil(funcionario2);//erro
end;[/b:a3daaefe8c]

Eu crio um objeto e passo por referência para outro objeto. Depois eu destruo o 1º objeto e testo o 2º para saber se ele está ´assigned´. Se for true, eu destruo o 2º objeto, mas dá erro, porque agora ele aponta para um endereço de memória inválido, ou seja, quando eu destrui o 1º objeto, o 2º não se deu conta de que a memória não está mais disponível.

Como faço para o assigned funcionar?


Alissonmn

Alissonmn

Responder

Post mais votado

16/07/2019

O Delphi é uma besta poderosa porque alia coisas das linguagens de mais baixo nível, tais como ponteiros, e coisas mais novas como [i]generics[/i].

Tem uma questão conceitual nesse ponto:

funcionario2 := funcionario1;


Você está fazendo o ponteiro funcionario2 receber o valor do ponteiro funcionario1. O objeto na memória é o mesmo, você tem dois ponteiros apontando para o mesmo lugar.

Quando você faz isso:

FreeAndNil(funcionario1);


Você está destruindo o objeto para onde o ponteiro funcionario1 aponta, e também está dizendo que esse ponteiro aponta para "o nada" (nil).

Logo depois disso, seu código deveria ser: funcionario2 := nil. Isso seria a forma segura de trabalhar. Seu código não poderia ser FreeAndNil(funcionario2), porque isso tentaria destruir o objeto pela segunda vez, e geraria um [i]Access Violation[/i].

Se você quer criar uma coisa em que pode ir pegando ponteiros de um objeto, destruir um deles e isso limpar os outros, terá que escrever código. É um bom desafio pra entender bem a lógica dos ponteiros/objetos.

Exemplo:

funcionario1 := TFuncionario.Create;
funcionario1.getManagedPointer(funcionario2);

Na destruição da classe, você varreria a lista interna e faria os outros ponteiros serem forçados para [b]nil[/b].

Daria um pouco de trabalho, mas ficaria uma solução bem bonita.

Iverson Farias

Iverson Farias
Responder

Mais Posts

27/03/2008

Massuda

Como faço para o assigned funcionar?
Você está assumindo que Assigned() testa se um valor é válido, mas na verdade Assigned() testa apenas se o valor não é nil.


Responder

27/03/2008

Alissonmn

Entendo, mas como verificar se o endereço é válido?


Responder

27/03/2008

Massuda

Não existe nada pronto em Delphi que sirva para testar se (vou ser específico) uma referência a um objeto é uma referência válida.

Explique melhor seu problema, já que certamente o código que você postou deve ser uma versão simplificada do problema.


Responder

27/03/2008

Rodc

Testei no C++, por isso não sei se a sintaxe do Delphi está correta. Sugiro usar esta verificação apenas dentro da função que destruiu funcionario1.
if (Assigned(funcionario2)) and (csDestroing in funcionario2.ComponentState) then //ainda aponta memória que funcionario1 ocupava porém funcionário 1 está sendo destruido
funcionario2 := nil;



Responder

27/03/2008

Massuda

if (Assigned(funcionario2)) and (csDestroing in funcionario2.ComponentState) then...
No seu exemplo, TFuncionario deve ser um classe derivada de TComponent, o que pode não ser verdade neste caso.


Responder

27/03/2008

Rodc

...TFuncionario deve ser um classe derivada de TComponent, o que pode não ser verdade neste caso.

É verdade!


Responder

27/03/2008

Alissonmn

De fato, a classe funcionário é um TComponent. Tentei usar ComponentState, mas não funcionou.

Encontrei uma solução aqui mesmo no fórum. Trata-se de uma rotina que valida o objeto.

[b:3b3196295f]function ValidateObj(Obj: TObject): boolean;
type
PPVmt = ^PVmt;
PVmt = ^TVmt;
TVmt = record
SelfPtr : TClass;
Other : array[0..17] of pointer;
end;
var
Vmt: PVmt;
begin
Result := true;
if Assigned(Obj) then
try
Vmt := PVmt(Obj.ClassType);
Dec(Vmt);
if Obj.ClassType <> Vmt.SelfPtr then
Result := false;
except
Result := false;
end;
end;[/b:3b3196295f]


Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

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

Aceitar