Assigned(my_var)求值为True,其中var的计算结果为Nil(!! ??)

时间:2013-06-10 01:55:46

标签: delphi null

它可能不相关,但我最近重新安装了Delphi XE2。

我有一个变量path(TPath类型,一个TMS Gogole映射的东西,虽然我怀疑这很重要)。

我在调试器中暂停并评估path,其评估为Nil

如果我跑,我会得到一个例外,Read of address 0,我怀疑是因为这个。

当我然后评估Assigned(path) path = NilTrueShowMessage(当我停在var行时执行相同的结果)

有人可以向我解释一下吗?

清洁&重建没有任何改变。可能最好删除&重新安装Delphi?

(向@mbratch道歉,我使用path进行演示,真实姓名是This was retested here with:}


[更新]由TMS提供并为他们工作的完整代码示例(在不同的领域,这也是我在这里问的原因)。

uses uwebgmapspolylines; procedure TForm1.FormCreate(Sender: TObject); var p: TPath; begin p := TPath.Create; if Assigned(p) then ShowMessage('creation OK'); end;

and this proves the correct creation of TPath returns a valid instance.

if Assigned(p) then

当我停在p并评估Nil时,我得到Assigned(p),但当我评估True时,我得到p <> Nil

当我将光标悬停在IDE中的变量声明上时,显示该类型是在UWebGMapsPolyLines中声明的


[更新]两票结束?真的吗?我想那些人认为这不可能 - 而且它就是!!!

奇怪的是@j尝试了它并获得了p = Nil。但是,我在第二台PC上尝试了它,并且仍然使用由TMS提供的此处发布的代码获得if System.Assigned(p)

我承认这看起来很奇怪,但我可以在2台电脑上重现它。 P是Nil,但它是Assigned()。

我没有Assigend()的代码进入。此外,我稍微将代码更改为显式{{1}},但仍然得到相同的结果。有什么建议吗?

Assigned, or not?

1 个答案:

答案 0 :(得分:2)

我使用了你的代码(使用Delphi XE2),发现了这个:

TPath breakpoint

TPath watch

您是否对FOwner = nil p = nil感到困惑? TPath继承自TPersistent,因此您可以将其传递给所有者(尽管这样做是可选的)。例如,您可以这样做:

 p := TPath.Create(self);

修改

试试这个:

   var p:TPath
   begin
*1   if assigned(p) then ShowMessage('foo');
     p:=nil;
     if assigned(p) then ShowMessage('bar');
     p:=TPath.Create;
     if assigned (p) then ShowMessage('ok');
   end;

将断点放在*1上 - 您应该在监视器或局部变量窗口中看到:

 p       *Inaccessible Value*

非引用计数引用类型的局部变量未初始化为零/零 - 它们包含分配给它们的空间中发生的任何随机数据。 '无法访问的值'意味着无论随机数据是什么,它都不会指向程序内存空间中的可读内存地址。

步入下一行 - &gt; 'foo' - &gt; if assigned(p)...

你看到的消息......为什么?! Assigned只检查nil - 因为局部变量未初始化,Assigned返回true(它不知道你给它一个未初始化的局部变量 - 它只知道你给它的东西不是{{ 1}})。这也是为什么释放未初始化的局部变量是个坏主意。

步入下一行 - &gt; p:= nil - &gt; nil

当您跳过p:= nil时,您会看到无法访问的值更改为:

if assigned(p)...

你不会看到消息'bar'(记住,分配(p)只检查 p nil )。请注意nil在手表中是赤裸裸的 - 没有括号!一直到最后,您会在手表创建后再次看到nil的值更改:

p

就像Sertac在评论中解释的那样,当一个对象被创建时,watch / locals窗口会在括号中显示它们的成员内容。以上显示 p (nil) 不是p没有括号),它不是未初始化的(即:不可访问的值),并且它还包含一个成员字段(展开显示为nil),该字段已初始化为nil且尚未赋值。

简短的教训是FOwner仅对字段或全局变量非常有用,而对非引用计数的局部变量非常有用 - 前者在创建对象时初始化为Assigned,后者不是(当你输入方法时)。