9

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

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

  { Real code for this method}

我想这会阻止我尝试在空对象指针上调用方法。但是在这种情况下,一旦我尝试访问成员数据,我就会得到一个例外,对吧?

这是我以前从未见过的某种标准吗?有问题的对象来自 TPersistent。

4

6 回答 6

10

抱怨 nil 指针的明显错误比没有说明它是如何发生的访问冲突要好。

于 2009-06-24T21:13:51.087 回答
10

您可以在空指针上调用实例方法,尽管这不是您想要刻意做的事情。当这种情况发生时,执行会非常愉快地继续进行,直到它需要访问实例数据,然后一切都会顺利进行。

在这种情况下,检查 nil 会在过程的顶部提醒您,以便您可以执行不同的操作,例如记录堆栈跟踪。或者你可以在加注线上设置一个断点,这样你就可以潜入水中看看发生了什么。

即,如果我有一个特定的错误我试图追踪使用 nil 引用的位置,我可能会这样做。

经常这样做让我觉得代码有异味。

于 2009-06-25T04:57:45.727 回答
4

有些访问冲突场景可能导致代码在 Self 为 nil 的内存中运行。一些程序员,而不是解决真正的问题,试图绕过使用这样的断言,以防止各种损坏。我会很好地检查该异常是否在运行时引发,如果是这样 - 你手中有错误的代码。

您可以阅读以下有关该主题的文章:当 Self in Nil... You Know You are in Trouble 时

另一种可能性与事件有关,您可以在此处阅读更多内容,其中包含大量此类测试的示例以及相应的解释:多播事件 - 第 2 部分

于 2009-06-24T20:51:16.187 回答
3

这种情况肯定会导致崩溃(即操作系统异常,例如“从地址 0x00000000 读取”)。抛出一个语言异常只是多余的(在这里滥用 EAbstractError 并不能让它变得更好)。

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

应该注意一个例外:在 Delphi 中,Free可以在 nil 指针上调用该方法,这当然需要这种检查。

于 2009-06-25T08:03:15.610 回答
1

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

尽管如此,这还是将防御性编程发挥到了极致。我从来没有(好吧,几乎从来没有 - 只有当我在猎捕 wabbits 时... errr ... squashing bugs)这样做。

于 2009-06-24T21:55:54.947 回答
1

似乎该方法的初衷是它成为一种抽象方法。

于 2009-06-24T22:48:43.127 回答