批判,再批判!关于“探究:如何判断Delphi中的对象指针是否可用”!

    01年本人发表了一篇文章,名为“探究:如何判断Delphi中的对象指针是否可用”。在文中,提出了采用对已经释放的对象进行有选择的属性/方法的访问或调用,然后以是否出现异常来判断其对象指针是否可用。

   这种方法荒谬之极!我想以如下程序的运行现象来帮助各位做出明智的判断。

    unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    btn1: TButton;
    btn2: TButton;
    btn3: TButton;
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure btn3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.btn1Click(Sender: TObject);
var
  a: TComponent;
  s: String;
begin
  //Do Create a comonent and free it.
  a := TComponent.Create(Self);
  a.Name := 'a_Name';
  a.Tag := 1111;
  s := a.GetNamePath;
  a.Free;

  //Try to access object's method or propery.
  Assert(a.Name <> 'a_Name'); //成立!理由是字符串被释放后,其长度变为0,因此为空串
  Assert(a.Name = '');//成立!
  Assert(a.Tag = 1111);//成立!
  Assert(a.ComponentState = [csDestroying, csAncestor]);//成立!
  a.FindComponent('');//通过!内部有对象访问的保护。
  a.Name := 'NewName'; //异常!Exception.Name = EAccessViolation; Exception.Message: 'access violation at address 0000000. Read of address 00000000'
  a.GetParentComponent;//异常!代码停留在 sytem.GetDynaMethod。"access violation ... read of Address 00000007."
  Assert(a.GetParentComponent = Self);//异常!代码停留在 sytem.GetDynaMethod。"access violation ... read of Address 00000007."
  Assert(a.GetNamePath = s); //异常!代码停留在 sytem.GetDynaMethod。"access violation ... read of Address 00000007."
end;

procedure TForm1.btn2Click(Sender: TObject);
var
  a, b: TComponent;
begin
  //Do Create a comonent and free it.
  a := TComponent.Create(Self);
  a.Name := 'a_Name';
  a.Tag := 1111;
  a.Free;

  //Assert it.
  b := TComponent.Create(Self);
  b.Name := 'b_Name';
  b.Tag := 2222;
  try
    Assert(a = b); //成立!为什么?
  finally
    b.Free;
  end;
end;

procedure TForm1.btn3Click(Sender: TObject);
var
  a, b, c: TComponent;
  s: String;
begin
  a := TComponent.Create(Self);
  a.Name := 'a_Name';
  a.Tag := 1111;
  s := a.GetNamePath;
  a.Free;

  c := TButton.Create(Self);

  b := TComponent.Create(Self);
  b.Name := 'b_Name';
  b.Tag := 2222;

  try
    Assert(a <> b);
    Assert(a <> c);
    Assert(a.Name <> 'a_Name'); //成立!等于原来值的可能性极小!
    Assert(a.Name <> '');//成立!理由:为空的可能性极小,但也不是没有可能。
    Caption := a.Name; //Caption 为一堆乱码!
    Assert(a.Tag <> 1111);//成立!
    Caption := IntToStr(a.Tag); //Caption 为一个随机整数。
    Assert(a.ComponentState = []);//成立!
    a.FindComponent(''); //通过!内部有对象访问的保护。
    a.Name := 'NewName'; //异常!停留在 Controls.procedure TControl.Click; 处。Exception.Name = EAccessViolation; Exception.Message: 'access violation at address 00200041. Read of address 00200041'
    a.GetParentComponent;//异常!EAbstractError. 停留在 SysUtils单元的procedure AbstractErrorHandler;处。 与上面类似,read of Address 00000007.
    Assert(a.GetNamePath <> s); //通过!
    Caption := a.GetNamePath; //Caption 为'TFont'。为什么?
  finally
    b.Free;
    c.Free;
  end;
end;

end.

    综上所述,对象指针的后续使用,依赖于该对象释放之后程序的具体行为。若恰好有一个相同类型的对象马上创建,则很可能两者刚好相同。而如果后续未创建任何对象,以及未申请内存,则部分对象方法或属性其具有特定的值。倘若后续内存有些别样的变化,则结果又不相同。其机理是delphi对对象的创建和销毁的内存管理的问题——想要简单地采用某种方式进行指针是否可用的判断是多么的肤浅和无知啊。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值