Objective-c 有意向已释放对象发送消息的示例代码

Objective-c example code that intentionally messages a deallocated object

我是 objective-cxcode 的新手,我目前正在编写的一个应用是收到臭名昭著的 EXC_BAD_ACCESS 错误。

几乎每个人都建议开始使用 NSZombies 来解决问题。我想我有 NSZombies 工作,但是 xcode 没有给我关于 zombie 在我的应用程序崩溃时收到消息的警报。

在我继续调试之前,我想 运行 一些代码,这些代码肯定会导致消息被发送到 zombie(de -分配的对象)。

什么是简单的代码片段,其中消息被发送到已释放的对象,导致 NSZombies 应该提醒我的场景?

对于非 ARC 代码:

- (IBAction) messageZombie:(id)sender {
    id a = [[NSObject alloc]init];
    [a release];
    NSLog(@"%@", [a description]);
}

这将在关闭 Zombies 的情况下向您提供 EXC_BAD_ACCESS,并在启用 Zombies 的情况下显示 "message sent to deallocated instance" 消息。

如果您的项目使用的是 ARC,那么要可靠地将消息发送到取消分配的对象(毕竟是 ARC 的要点)会有点困难。

这个有效:

- (IBAction) messageZombie:(id)sender {    
    id a = [[NSObject alloc]init];
    id __unsafe_unretained b =a;
    a=nil;
    NSLog(@"%@", [b description]);
}

它可能与您的实际代码所做的不太相似,因为到底是谁在使用 __unsafe_unretained?但是如果你只是想确保你已经正确打开了 NSZombies,这应该是一个合理的测试用例。

如果您要查找代码中的可疑位置,请务必查找 __unsafe_unretained 指针,尽管您不会找到任何指针*,并仔细检查是否为 CoreFoundation 使用了正确的转换转换为 Cocoa 个对象的对象。

* 如果你的项目需要支持OS X 10.7之前的版本,或者iOS 5.0之前的版本,那么就不能使用__weak指针,所以在那种情况下的项目,您会发现 __unsafe_unretained 被更频繁地使用。

您可以创建一个 CF 对象,将其桥接到 Objective-C 对象,然后释放它并尝试使用桥接对象。我认为您必须使用 __bridge 才能使其按照您想要的方式运行。