如何检查物体是否已经被破坏? [英] How to check if an object is already destroyed or not?

查看:106
本文介绍了如何检查物体是否已经被破坏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  1. 我创建了一个对象

  2. 我将其作为参数传递给了其他地方。
  3. 在我的编码结束时,我尝试检查该对象是否有效,然后销毁它。 Assigned()方法返回true(似乎是因为该变量存储了对象引用地址)。但是,被引用的对象已准备好销毁,并且出现异常。

我的问题是,如何检查对象已经被销毁了?除Assigned()之外,还有什么可以检查对象是否仍然存在?

My question is, how could I check if an object is already destroyed? What else other than Assigned() can check the object still exists or not?

program Project1;
uses System.SysUtils;

type TObj = class
  public
    Name: string;
end;

var AnObj, AnObj2 : TObj;
begin
  try
    try
      AnObj := TObj.Create;
      AnObj.Name := 'Testing';

      AnObj2 := AnObj;     // AnObj passed to other procedures as param
      FreeAndNil(AnObj2);  // somewhere else "Free" the object out of my control
      // as a result, AnObj is still assigned but the object is destroyed
    finally
      if Assigned(AnObj) then // AnObj is assigned, HOW COULD I IMPROVE HERE?
        FreeAndNil(AnObj);    // Exception: Invalid pointer operation
    end;
  except
    on E:Exception do
      writeln(E.Message);
  end;
  readln;
end.


推荐答案


如何检查

How to check if an object is already destroyed or not?

简短的答案是不能。没有任何机制可以让您在手动内存管理下检查对象的有效性。

Short answer is you can't. There is no mechanism that will allow you to to check validity of object under manual memory management.

如果您想跟踪有效性以进行调试,则可以使用自定义内存管理器(如处于完全调试模式的FastMM),该跟踪器可以跟踪所有引用并在访问时报告悬空的指针。

If you want to track validity for debugging purposes, you can use custom memory manager (like FastMM in full debug mode) that can track all references and will report when you access dangling pointers.

FreeAndNil Assigned相结合仅在您具有单个引用的对象时才有效。如果您有更多引用,它会崩溃,因为 FreeAndNil 只能引用您引用的引用,而 nil 。所有其他引用将变为悬空指针,并且 Assigned 无法检测到悬空指针。

FreeAndNil in combination with Assigned only works when you have single reference to an object. If you have more it falls apart because FreeAndNil can nil only the reference you called it upon. All other references will become dangling pointers and Assigned cannot detect dangling pointers.

简而言之, Assigned 仅在引用指向有效对象实例或包含 nil 值时有效。在手动内存管理下,如果需要使用 Assigned ,则必须跟踪并确保引用始终包含有效值。

In a nutshell, Assigned works only when reference points to valid object instance or contains nil value. Under manual memory management you have to keep track and make sure that your reference always contains valid value if you need to use Assigned.

在保留对一个对象的单个引用时使用 Assigned

Using Assigned when you keep single reference to an object

如果您具有对对象的单一引用,可以使用 Assigned 进行惰性初始化模式,如果尚未创建对象实例,则可以在其中创建对象实例。但是您必须确保对象引用首先包含 nil 引用。

If you have single reference to object, you can use Assigned for lazy initialization pattern where you will create object instance if it is not already created. But you have to make sure that object reference contains nil reference in the first place.

仅当对象引用是类字段,对象实例字段或全局变量时,它们才会自动初始化为 nil

Object references will be automatically initialized to nil only if they are class fields, object instance fields or global variables.

如果您不打算在对象引用发布后重用该对象,则可以使用 Free 释放对象引用内存。

If you don't plan to reuse that object reference once it is released you can use Free for releasing its memory.

如果您有可重用的引用,则要在其中多次创建和释放对象实例,则必须使用 FreeAndNil ,或在调用 Free 后将引用设置为nil。这是确保 Assigned 在对象释放后可以正常工作的唯一方法。同样,此 Assigned / FreeAndNil 模式仅在您保留对该对象的一个​​引用且只有一个引用的情况下有效。

If you have reusable reference, where you want to create and release object instance multiple times, you have to use FreeAndNil, or set reference to nil after you call Free. That is the only way you can ensure Assigned will work after object is released. Again, this Assigned/FreeAndNil pattern only works if you keep one and only one reference to that object.

当您保留对一个对象的多个引用时,使用已分配

Using Assigned when you keep multiple references to an object

如果可能,永远不要保留对一个对象实例的多个引用。如果您确实必须保留对一个对象实例的多个引用,则需要实现某种机制以确保您可以通知所有引用该对象不再有效。

If possible don't ever keep more than one reference to an object instance. If you have scenario where you really must keep multiple references to an object instance you need to implement some mechanism that will ensure you can notify all references that object is no longer valid.

有几种方法:


  1. 使用界面-自动内存管理将防止指针悬空

  2. 使用 TComponent 作为基类-您可以在对象实例为状态时使用其通知系统获取通知将被销毁

  3. 实施您自己的通知系统来管理对对象实例的所有引用

  1. Using interfaces - their automatic memory management will prevent dangling pointers
  2. Using TComponent as base class - where you can use its notification system to get notifications when object instance is going to be destroyed
  3. Implement your own notification system to manage all references to an object instance

注意:对于2和3.,您必须手动 nil 收到对对象的通知时将销毁该对象的所有引用。如果不这样做,则未设置为 nil 的任何引用都将无效,使用 Assigned 它将无法正常工作。

Note: For 2. and 3. you have to manually nil all references to an object when you get notification it will be destroyed. If you don't do that any reference you don't set to nil, will be invalid, dangling reference any using Assigned upon it will fail to work properly.

如果您遇到将对象作为参数传递的情况,并且某些无法控制的代码称为在该对象上免费,然后您要处理所有权转移。您创建了对象,但是随后将所有权(发布对象的责任)转移到了其他一些代码。之后,您不应再使用该对象引用(在某些狭窄的情况下,除非确定传输完成后的即时代码不会触发对象释放)。

If you have situation when you passed object as parameter, and some code beyond your control called Free on that object then you are dealing with ownership transfer. You created the object, but then you transferred ownership (responsibility to release object) to some other code. After that you should not use that object reference again (except in some narrow scenarios, when you know for sure that immediate code after transfer is complete will not trigger object release).

只有在有某种通知机制(如前所述)可以释放对象实例时通知您时,您才可以使用不拥有的对象引用(在转让所有权之后)。

You can use object reference you don't own (after you have transferred ownership) only if there is some notification mechanism (as mentioned earlier) that can notify you when object instance is released.

也永远不要释放您不拥有的对象。在您的示例中,即使可以通知您对象将被销毁,您只能做的是 nil 指向该对象的引用。您不应尝试释放它。

Also you should never, ever free objects you don't own. In your example, even if you can get notified that object is going to be destroyed all you can do is nil the reference that points to it. You should not attempt to release it.

这篇关于如何检查物体是否已经被破坏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆