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