technologies software mexico descargar autopartes delphi

software - delphi technologies



Mala referencia a un objeto ya liberado (7)

Como han dicho otros, no hay una forma definitiva, pero si administra bien la propiedad, entonces la rutina FreeAndNil se asegurará de que su variable sea nula si no apunta a nada.

¿Hay alguna manera de asegurarnos de tener una referencia utilizable de un objeto, es decir, de estar seguros de que no ha sido liberado dejando esa referencia no nula colgando?


Con el uso de referencias de interfaz (en lugar de referencias a objetos) es posible evitar estos problemas de puntero no válido porque ya no hay una llamada explícita a Free en su código.


Estándar, no ...

Es por eso que los componentes de VCL pueden registrarse para recibir notificaciones de la destrucción de un objeto, de modo que puedan eliminar la referencia de su lista interna de componentes o simplemente restablecer su propiedad.

Por lo tanto, si quiere asegurarse de que no tiene ninguna referencia no válida, tiene dos opciones:

  • Implementa un controlador de notificación de destrucción al que todas las clases pueden suscribirse.
  • Repare su código de forma que las referencias no se distribuyan a través de diferentes objetos. Por ejemplo, solo puede proporcionar el acceso a la referencia a través de una propiedad de otro objeto. Y en lugar de copiar la referencia a un campo privado, accede a la propiedad del otro objeto.

Lamentablemente, no hay forma de garantizar al 100% que un puntero a cualquier cosa siga siendo válido, excepto escribiendo meticulosamente el código correcto.


No. A menos que use algo como el recuento de referencias o un recolector de basura para asegurarse de que ningún objeto se liberará antes de que tengan cero referencias.

Delphi puede hacer recuentos de referencia para usted si usa interfaces. Por supuesto, Delphi for .Net tiene un coleccionista de gárgaras.

Como se mencionó, puede usar el conocimiento de Delphi o las funciones internas del administrador de memoria para verificar punteros u objetos válidos, pero no son los únicos que pueden darle punteros. Entonces no puedes cubrir todos los punteros incluso con esos métodos. Y también existe la posibilidad de que su puntero vuelva a ser válido, pero se lo entregue a otra persona. Entonces, no es el puntero que estás buscando. Tu diseño no debe confiar en ellos. Usa una herramienta para detectar cualquier error de referencia que hagas.


Por lo general, no es una buena idea verificar que una referencia sea válida de todos modos. Si una referencia no es válida, su programa se bloqueará en el lugar donde está utilizando la referencia no válida. De lo contrario, la referencia no válida podría durar más tiempo y la depuración se vuelve más difícil.

Aquí hay algunas referencias de por qué es mejor colgarse de una referencia no válida. (Hablan de punteros en Win32, pero las ideas siguen siendo relevantes):


Si está utilizando FastMM4 como su administrador de memoria, puede verificar que la clase no sea TFreeObject .
O, en un caso más estándar, use una rutina que verifique que su objeto es lo que dice al consultar la clase VMT .

Ha habido tales funciones de ValidateObj dando vueltas por algún tiempo (por Ray Lischner y Hallvard Vassbotn: http://hallvards.blogspot.com/2004/06/hack-6checking-for-valid-object.html )

Aquí está otro:

function ValidateObj(Obj: TObject): Pointer; // see { Virtual method table entries } in System.pas begin Result := Obj; if Assigned(Result) then try if Pointer(PPointer(Obj)^) <> Pointer(Pointer(Cardinal(PPointer(Obj)^) + Cardinal(vmtSelfPtr))^) then // object not valid anymore Result := nil; except Result := nil; end; end;

Actualización: Un poco de precaución ... La función anterior asegurará que el resultado sea nulo o un Objeto no nulo válido. No garantiza que el Obj siga siendo lo que crees que es, en caso de que el Administrador de memoria ya haya reasignado esa memoria previamente liberada.