我正在查看一些代码(Delphi 7),以下检查位于特定对象的每个方法调用的顶部:
if not Assigned(self) then
raise Exception.CreateRes(@sAbstractError);
{ Real code for this method}
我想这会阻止我尝试在空对象指针上调用方法。但是在这种情况下,一旦我尝试访问成员数据,我就会得到一个例外,对吧?
这是我以前从未见过的某种标准吗?有问题的对象来自 TPersistent。
抱怨 nil 指针的明显错误比没有说明它是如何发生的访问冲突要好。
您可以在空指针上调用实例方法,尽管这不是您想要刻意做的事情。当这种情况发生时,执行会非常愉快地继续进行,直到它需要访问实例数据,然后一切都会顺利进行。
在这种情况下,检查 nil 会在过程的顶部提醒您,以便您可以执行不同的操作,例如记录堆栈跟踪。或者你可以在加注线上设置一个断点,这样你就可以潜入水中看看发生了什么。
即,如果我有一个特定的错误我试图追踪使用 nil 引用的位置,我可能会这样做。
经常这样做让我觉得代码有异味。
有些访问冲突场景可能导致代码在 Self 为 nil 的内存中运行。一些程序员,而不是解决真正的问题,试图绕过使用这样的断言,以防止各种损坏。我会很好地检查该异常是否在运行时引发,如果是这样 - 你手中有错误的代码。
您可以阅读以下有关该主题的文章:当 Self in Nil... You Know You are in Trouble 时。
另一种可能性与事件有关,您可以在此处阅读更多内容,其中包含大量此类测试的示例以及相应的解释:多播事件 - 第 2 部分。
这种情况肯定会导致崩溃(即操作系统异常,例如“从地址 0x00000000 读取”)。抛出一个语言异常只是多余的(在这里滥用 EAbstractError 并不能让它变得更好)。
在不安全的语言中检查有效的输入参数不是一项可行的任务,因为您永远不会获得确定性,因此您对无效参数的处理将永远不会一致。(为什么在传递 nil 指针时抛出异常,而不是 0x00000001,这同样无效?)。有关此问题的更多技术讨论,请阅读 Larry Osterman 的博客,了解为什么不检查有效指针。
应该注意一个例外:在 Delphi 中,Free
可以在 nil 指针上调用该方法,这当然需要这种检查。
然后总是有可能代码在使用 nil Self 运行时不会崩溃。示例 - 如果它没有访问所有者对象的任何字段。在这种情况下,此测试将捕获否则无法检测到的问题。
尽管如此,这还是将防御性编程发挥到了极致。我从来没有(好吧,几乎从来没有 - 只有当我在猎捕 wabbits 时... errr ... squashing bugs)这样做。
似乎该方法的初衷是它成为一种抽象方法。