【问题标题】:Why I don't receive Exception if I use the object after I destroy it?如果我在销毁对象后使用该对象,为什么我不会收到异常?
【发布时间】:2017-06-25 17:04:08
【问题描述】:

以下代码可以正常工作,但不应该!当我单击 Button1 时,首先销毁该对象,然后使用它的值,并且我没有收到任何访问冲突或其他东西......更重要的是,乘法运算给出了正确的结果,证明 Obj1 是不破坏!但是话又说回来,这也不是真的,因为当我关闭程序时,它不会报告任何内存泄漏。我很困惑。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  MyObj = class(TObject)
   Value: Cardinal;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  public
   Obj1:MyObj;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Obj1.Free;
 Obj1.Value:=Obj1.Value * 5;
 Caption:=IntToStr(Obj1.Value);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 ReportMemoryLeaksOnShutdown:=true;
 Obj1:=MyObj.Create;
 Obj1.Value:=10;
end;

end.

【问题讨论】:

  • 因为内存还有效;那时您只是在写入内存位置。那时你可能会在其他物体上乱涂乱画。

标签: delphi runtime-error delphi-2009


【解决方案1】:

对象被销毁。内存返回给内存管理器。接下来发生的事情是你无法控制的。内存可以返回给系统。在这种情况下,您会看到运行时错误。或者,内存可以由内存管理器保持活动状态,以便在程序下次请求该大小的块时重新使用。这就是这里发生的事情。

您的程序表现出未定义的行为。任何事情都可能发生,包括该程序似乎可以工作。显然程序是错误的,你不能在对象被销毁后访问它们。

如果您使用 FastMM 的完整调试版本,那么您应该会看到一个错误,因为在这种情况下会采取步骤来检测释放后的访问。这是一个有用的调试工具。

【讨论】:

  • 不将 NIL 分配给已释放的对象会有所帮助吗?
  • @GuidoG 将 NIL 分配给该引用并不一定有帮助,因为可能还有其他引用。
  • @GünthertheBeautiful 是的,我知道悬空指针的情况,但是在 OP 的示例代码中,他会执行 Obj1 := NIL;在 free 之后会再次引发异常,对吧?
  • @David 我不确定 FastMM 能否检测到 。我看到 FastMM 可以检测已释放的接口引用以及对已销毁对象的虚拟方法调用。我看不到为读出一个简单字段引发异常的选项。你能提供 FastMM 选项吗?
  • @GünthertheBeautiful 你可能是对的,我可能记错了它可以做什么
猜你喜欢
  • 2020-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-23
  • 1970-01-01
相关资源
最近更新 更多