有没有办法在Objective-C中捕获发送到nil的消息?

时间:2009-05-27 05:56:51

标签: objective-c debugging null

我刚刚被一个令人讨厌的bug所困扰,而这一点被Objective-C中的“发送消息给nil是好的”行为所掩盖。

我见过Sending a message to nil?,而且共识似乎是'我们如何在Objective-C中滚动'。

现在,也许我没有足够的Objective-C经验,但似乎陷入困境似乎很有用,因为我无法想到为什么会发生这种情况 most < / em>的时间。然而,它可能只是一个我不习惯的编码习语。

除了像以下那样检查nil之外:

assert( object != nil );
[object message];

有没有办法让运行时捕获这种情况,并在object为零时发出警告?

2 个答案:

答案 0 :(得分:9)

您可以使用ObjC undocumented trick or dtrace(请参阅dtrace解决方案的注释)。

pid$1::objc_msgSend:entry
/arg0==0/
{
  ustack();
}

答案 1 :(得分:4)

nil消息传递在ObjC中非常常用。人们可以争论这是好还是坏;这只是你必须习惯的东西。如果你试图用技巧打破它,那么你将打破Cocoa,因为Cocoa使用它。有一些技巧(如发布的diciu)可以在你怀疑没有消息的情况下进行调试,但似乎无法找到它。但是你不能把这些留在你的代码中(上面的博客文章清楚地说明了这一点)。零消息在框架内部太常见了。

至于你原来的观点,比较:

- (void)doSomethingWith:(id)x {
    NSAssert(x != nil, @"Don't pass me nil");
    [x something];
}

VS

void Bar::DoSomething(Foo *x) {
    assert(x != NULL);
    if (x != NULL) {
       x.something;
    }
}

在这两种情况下,您都需要进行测试,在这两种情况下,如果您未通过测试,编译器将不会发出警告。唯一的区别是你崩溃/断言的情况。就个人而言,我在NSAssert()周围编写宏,使其始终打印日志消息(如果失败)。它只是在Debug中崩溃。这样,当客户向我发送日志时,我可以看到哪些断言失败了。