Fórum como saber se um ponteiro não-nil tem uma referencia valida? #330748
05/10/2006
0
Meu problema é o seguinte: fazer uma função que execute o método free em todos os objetos de um array de objetos.
procedure LimpaTudo(vObjetos: array of TObject); var i: Integer; o: TObject; begin try for i := Low(vObjetos) to High(vObjetos) do begin if not isNil(vObjetos[i]) then begin o := TObject(vObjetos[i]); MessageBox(0, PChar(string(o.ClassName)), ´limpando´, 0); Pointer(vObjetos[i]) := nil; o.Free; Pointer(o) := nil; end; end; except end; end;
a função isnil está abaixo:
function isNil(pObjeto: tobject): boolean; begin if (pobjeto = nil) then MessageBox(0, ´objeto = nil´, ´teste´, 0) else MessageBox(0, ´objeto <> nil´, ´teste´, 0); if (not assigned(pobjeto)) then MessageBox(0, ´objeto not assigned´, ´teste´, 0) else MessageBox(0, ´objeto assigned´, ´teste´, 0);; isNil := ((pobjeto = nil) or (not assigned(pobjeto))); end;
ela me retorna true caso o objeto seja nil ou caso ele não esteja assigned.
o problema é que se eu coloco pra liberar 3 vezes o mesmo objeto, tipo assim :
LimpaTudo([Edit1, Edit1, Edit1]);
ocorre access violation, pois isnil retorna true sempre. O que eu faço?
Vitor Rubio
Curtir tópico
+ 0Posts
05/10/2006
Massuda
var O: TObject; ... O := nil O.Free; ...
Gostei + 0
05/10/2006
Siam
Gostei + 0
05/10/2006
Siam
procedure LimpaTudo(var vObjetos: array of TObject); var i:Integer; begin for i := 0 to High(vObjetos) do FreeAndNil(vObjetos[i]); end;
Gostei + 0
05/10/2006
Vitor Rubio
Mas se eu der um free num objeto invalido, dá access violation. Testa meu código pra você ver.
Talvez seja isso, mas eu queria passar um array na hora. Se eu tivesse que passar um array por referência, teria que declarar um array primeiro e preenche-lo, e depois passa-lo.
Então no meu caso
[quote]procedure LimpaTudo(var vObjetos: array of TObject); var i:Integer; begin for i := 0 to High(vObjetos) do FreeAndNil(vObjetos[i]); end;
não daria certo, porque eu não tenho o array, estou criando na hora, como se fosse um array constante.
Existe algum outro jeito de se passar parametros infinitos para uma função?
como eu crio uma function igual a writeln do pascal antigo, que aceita um número variado-indefinido de parametros?
quero construir uma função que de free em varios objetos de uma vez sem usar listas.
Gostei + 0
05/10/2006
Massuda
O valor nil equivale numericamente ao zero. É fácil de testar. Free testa se o objeto é nil antes de chamar Destroy.
Um valor diferente de nil (numericamente não zero) pode ou não ser um objeto válido. O artigo que indiquei mostra como testar se um valor não-nil é ou não um objeto válido.
Gostei + 0
06/10/2006
Siam
Gostei + 0
06/10/2006
Vitor Rubio
Então, isso eu sabia. Mas como você deve ter visto no meu código, o problema é quando eu tenho duas variaveis diferentes, ou posições diferentes de um array de objetos, apontando para o mesmo objeto. Se eu der um free, ele vai liberar o objeto. Setando nil, ele vai setar só essa variavel pra nil, mas a ´copia´ dela não. A copia vai ficar com um ponteiro inválido, onde eu não posso dar free, e o assigned retorna true.
Precisaria de uma forma de liberar varios objetos de uma vez, com uma unica função.
Não entendi o artigo, ele disponibiliza uma biblioteca que só funciona em delphi 3 e que precisa de outras bibliotecas. A função principal dessa biblioteca usa uma outra que não está disponível.
Gostei + 0
06/10/2006
Massuda
Gostei + 0
06/10/2006
Vitor Rubio
function ValidateObj(Obj: TObject): Pointer; type PPVmt = ^PVmt; PVmt = ^TVmt; TVmt = record SelfPtr : TClass; Other : array[0..17] of pointer; end; var Vmt: PVmt; begin Result := Obj; if Assigned(Result) then try Vmt := PVmt(Obj.ClassType); Dec(Vmt); if Obj.ClassType <> Vmt.SelfPtr then Result := nil; except Result := nil; end; end;
ela não funciona nesse caso:
procedure TForm1.Button1Click(Sender: TObject); var o: TEdit; begin o := Edit1; edit1.Free; ValidateObj(o); o.Free; end;
que é o caso da minha procedure para limpar um array de objetos, não pode ter objetos repetidos. Alem disso, essa função é meio mistica: não entendi o porque de declarar PPVmt = ^PVmt; se não usa e tambem o porque que o ´Other : array[0..17] of pointer;´ é um array de 18 ponteiros....
de qualquer forma, valew!
Gostei + 0
06/10/2006
Siam
Gostei + 0
06/10/2006
Massuda
procedure LimpaTudo(vObjetos: array of TObject); var i: Integer; begin for i := Low(vObjetos) to High(vObjetos) do begin try vObjetos[i].Free; except // ignora problemas ao destruir end; end; end;
Duas perguntas:
* porque o array contem elementos duplicados?
* poderia dar uma idéia de como isso é usado?
Gostei + 0
06/10/2006
Vitor Rubio
É uma ótima solução mas eu não queria usar Tlist nesse caso.
isso funcionaria mais ou menos, mas ele ficaria parando nos exceptions, durante o debug, atrapalhando. As vezes vc pode ate confundir cm um erro de verdade.
Na verdade, um objeto repetido foi passado por engano, mesmo assim, não deveria dar essa exception ao liberar um objeto que já foi liberado. Se analisar a fundo, a minha procedure é mesmo inutil :oops: , mas quando deu esse erro surgiu essa curiosidade. O que eu queria era, ao inves de fazer:
objeto1.free; objeto2.free; objeto3.free; ... ... ... objeton.free;
fazer:
Limpatudo(objeto1, objeto2, objeto3....);
eu nem vou usar mais essa procedure. Valew pela ajuda!
Gostei + 0