¿Hay alguna manera de asegurarse de que tengamos una referencia utilizable para un objeto, es decir, de estar seguros de que no se ha liberado ya dejando esa referencia no nula colgando?Mala referencia a un objeto ya liberado
Respuesta
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, utilice una rutina que verifique que su objeto es lo que dice que es comprobando la clase VMT.
Ha habido tales funciones ValidateObj hannging alrededor por algún tiempo (por Ray Lischner y Hallvard Vassbotn: http://hallvards.blogspot.com/2004/06/hack-6checking-for-valid-object.html)
Aquí hay 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 ... Lo anterior La función se asegurará de que el resultado sea nulo o un objeto no nulo válido. No garantiza que el Obj siga siendo lo que usted cree que es, en caso de que el Administrador de memoria ya haya reasignado esa memoria previamente liberada.
Desafortunadamente, no hay forma de garantizar al 100% que un puntero a cualquier cosa siga siendo válido, excepto escribiendo minuciosamente 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 recuento de referencias si utiliza interfaces. Por supuesto, Delphi for .Net tiene un coleccionista de gárgaras.
Como se mencionó, puede utilizar el conocimiento de Delphi o las funciones internas del administrador de memoria para buscar 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.
estándar, no ...
Por eso componentes VCL pueden registrarse para ser notificado de la destrucción de un objeto, de modo que puedan eliminar la referencia de la lista hay interna de componentes o simplemente restablecer sus propiedades.
así que si desea asegurarse de que usted no ha conseguido ningún referencias inválidas su son dos opciones:
- implementar un controlador de notificación destrucción la que cada clase puede suscribirse.
- Corrija 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.
Como han dicho otros, no hay una manera definitiva, pero si administra bien la propiedad, entonces la rutina FreeAndNil se asegurará de que su variable sea nula si no apunta a nada.
Por lo general, no es una buena idea comprobar 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 a por qué es mejor colgarse de una referencia no válida. (Se habla de punteros en Win32, pero las ideas siguen siendo pertinentes):
Con el uso de referencias de interfaz (en lugar de referencias a objetos) es posible evitar estos problemas de puntero no válidos porque ya no hay una llamada explícita a Free en su código.
- 1. ¿NSArray: lastObject devuelve un objeto liberado automáticamente?
- 2. Cómo detectar cuándo ya no se hace referencia a un objeto
- 3. "ya tiene una referencia a" Essential.Diagnostics
- 4. Nuget "ya tiene una referencia a"
- 5. ¿Cómo hago referencia a un objeto dinámicamente?
- 6. Impresión de referencia a un objeto
- 7. Crear una referencia débil a un objeto
- 8. Malloc Error: suma de comprobación incorrecta para el objeto liberado
- 9. Objeto probablemente fue modificado después de ser liberado
- 10. intento de volver a abrir un objeto ya cerrado: SQLiteDatabase
- 11. Intento de volver a abrir un objeto ya cerrado: java.lang.IllegalStateException :?
- 12. django: select_related() en un objeto ya existente?
- 13. System.Security.Cryptography.CryptographicException -objeto ya existen
- 14. ¿Cómo resolver GC_concurrent liberado?
- 15. ¿Debo usar __bridge o __bridge_retained si estoy enlazando un objeto liberado automáticamente con Core Foundation?
- 16. ¿Cuándo no se puede convertir un objeto a una referencia?
- 17. ¿Cómo se hace referencia a un objeto en Lua?
- 18. Stringify (convertir a JSON) un objeto JavaScript con referencia circular
- 19. ¿Cómo inicializo boost :: any con una referencia a un objeto?
- 20. Almacenar una referencia a un objeto en C#
- 21. Pasando el parámetro de objeto a un funtor por referencia
- 22. ¿Es una mala práctica para un objeto secundario tener un puntero a su elemento primario?
- 23. Puntero no alineado liberado, en Java?
- 24. ¿Es una mala práctica hacer referencia a objetos Javascript desde elementos DOM?
- 25. C# lock en la referencia pasada al método - ¿mala práctica?
- 26. Usando la reflexión, llame a un método de un campo en un objeto que ya existe
- 27. En C++, ¿es un método const devolver un puntero a un objeto no const considerado mala práctica?
- 28. Crear referencia al nuevo objeto
- 29. ¿La referencia a un delegado constituye una referencia a un objeto (para evitar la recolección de basura)?
- 30. Añadir un punto entre cada objeto ya en la lista
@update: por lo tanto, en realidad no es una buena idea usarlo, porque dependiendo del administrador de memoria, es probable que su dirección se reutilice. Por lo tanto, no dará una respuesta definitiva. –
Si le dice que el objeto no es válido, esa * es * una respuesta definitiva, ¿no es así? En cuyo caso es útil. Acabo de usar esto y me ayudó a encontrar un error complicado. – awmross
Claro, es por eso que hice esta función: sin falsos positivos cuando encuentra un objeto malo, está garantizado que es malo. Bueno para levantar una bandera en ese caso, pero no puede garantizar que un objeto aún sea válido para que pueda confiar y usarlo. –