Assigned não funciona!
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?
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
Curtidas 0
Melhor post
Iverson Farias
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:
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:
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.
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.
GOSTEI 1
Mais Respostas
Massuda
27/03/2008
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.GOSTEI 0
Alissonmn
27/03/2008
Entendo, mas como verificar se o endereço é válido?
GOSTEI 0
Massuda
27/03/2008
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.
Explique melhor seu problema, já que certamente o código que você postou deve ser uma versão simplificada do problema.
GOSTEI 0
Rodc
27/03/2008
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;
GOSTEI 0
Massuda
27/03/2008
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.GOSTEI 0
Rodc
27/03/2008
...TFuncionario deve ser um classe derivada de TComponent, o que pode não ser verdade neste caso.
É verdade!
GOSTEI 0
Alissonmn
27/03/2008
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]
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]
GOSTEI 0