为什么在对象方法中要检查Assigned(self)?

9

我正在查看一些代码(Delphi 7),每个特定对象的方法调用顶部都有以下检查:

if not Assigned(self) then
  raise Exception.CreateRes(@sAbstractError);

  { Real code for this method}

我猜这样做可以避免我尝试在空对象指针上调用方法。但是如果我尝试在这种情况下访问成员数据,我会立即得到异常,对吗?

这是一种我从未见过的标准吗?所涉及的对象派生自TPersistent。

6个回答

10

一个清晰的错误提示关于空指针的问题比一个没有解释原因的访问违规更好。


1
捕获空指针而不是可能的访问冲突,加1分。 - Ian Boyd
一个空指针解引用不崩溃是非常困难的,你并没有拥有那里的内存。 - Loren Pechtel

10

尽管这不是你想有意做的事情,但你可以在空指针上调用实例方法。当发生这种情况时,执行会一直继续,直到需要访问实例数据,然后就会出错。

在这种情况下,检查是否为nil会在过程的顶部警告你,这样你就可以做一些不同的事情,比如记录堆栈跟踪。或者你可以在引发错误的代码行上设置断点,以便深入了解发生了什么。

也就是说,如果我正在尝试追踪一个使用了nil引用的特定Bug,我可能会这样做。

但是如果经常这样做,我认为这可能是一种代码异味。


4
有一些访问冲突的场景可能导致代码在Self为nil的内存中运行。一些程序员没有解决真正的问题,而是使用这种断言来绕过问题,以防止各种损坏。如果在运行时引发了该异常,请仔细检查 - 这意味着你手头有错误的代码。
您可以阅读以下文章了解更多信息:当Self为空时...你知道自己陷入了麻烦
另一个可能性与事件有关,您可以在此处阅读更多信息,并提供大量此类测试和相应的解释:多播事件-第2部分

2
我不会说这个示例代码完全绕过了真正的问题。相反,它明确地突出了问题。 - Rob Kennedy

3

这是一个绝对会导致崩溃的情况(例如操作系统异常,如“从地址0x00000000读取”)。抛出语言异常只是多余的(在此误用EAbstractError并不能使其更好)。

在不安全的语言中检查有效输入参数是不可行的,因为您永远无法获得确定性,因此您对无效参数的处理将永远不一致。(为什么当传递nil指针时会引发异常,但是当传递0x00000001时不会引发异常,而这也是无效的?)有关此问题的更多技术讨论,请阅读Larry Osterman有关不要检查有效指针的原因博客。

应该注意一个例外情况:在Delphi中,可以对空指针调用 Free 方法,这当然需要进行那种检查。


1

然后总有可能当使用 nil Self 运行时代码不会崩溃。例如 - 如果它没有访问所有者对象的任何字段。在这种情况下,这个测试将捕获本来无法检测到的问题。

尽管如此,这是极端防御性编程。我从不这样做(好吧,几乎从不 - 只有在我追逐兔子...呃...解决 bug 时)。


尽管我已经做到了,但使用非类方法作为类方法的形式很不规范。 - Ian Boyd

1

看起来该方法的原意是成为一个抽象方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接