为什么保留计数为0的对象会响应消息?

7st*_*tud 1 objective-c xcode6 ios8

关闭ARC:

  1. 我使用创建自定义类的实例alloc,因此它的保留计数为1.

  2. 在下一行,我NSLog()实例(我description在我的自定义类中实现了一个方法).

  3. 在下一行,我释放了该对象.

  4. 在下一行,我再次NSLog()实例,即我发送description消息,我在控制台中看到相同的输出.我期待某种错误输出.

这是相关代码:

AppDelegate.m:

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Override point for customization after application launch.

    Greeter* host = [[Greeter alloc] initWithName:@"Maggie"];  //My custom class
    NSLog(@"Greeter %@", host);
    [host release];

    NSLog(@"Greeter %@", host); //Create error: send a `description` message to an object whose retain count is 0.


    return YES;
}

...
...
Run Code Online (Sandbox Code Playgroud)

Greeter.m:

...

- (NSString*)description {
    return [
        [[NSString alloc] initWithFormat:@"\n\tname: %@ \n\tCreated on %@", [self name], [self today]]
        autorelease
    ];
}
Run Code Online (Sandbox Code Playgroud)

- 控制台中的输出: -

2015-04-26 21:18:58.914 Flashlight[2380:62826] Greeter 
    name: Maggie 
    Created on 2015-04-27 03:18:58 +0000
2015-04-26 21:18:58.915 Flashlight[2380:62826] Greeter 
    name: Maggie 
    Created on 2015-04-27 03:18:58 +0000
Run Code Online (Sandbox Code Playgroud)

类似的代码in cocoa会导致奇怪的事情发生,Xcode会标记第二个NSLog()EXC_BAD_ACCESS.

回复评论:

我决定开始一个新的应用程序尝试一些东西,这是我发现的:

  1. 在Xcode 6.2中,即使控制台中没有错误,即两个NSLog()打印相同的东西,Product>Analyze也会指出错误的行:Reference-counted object is used after it is released.如果我点击该消息,Xcode会在代码中显示一个很好的图解说明.

  2. 如果我edit the scheme启用Zombie对象,而不是第二个NSLog()消息,我收到一条错误消息:

Flashlight3 [606:11093]*** - [Greeter respondsToSelector:]:发送到解除分配的实例0x7fb5e1caa8c0的消息

在Xcode中浏览了太久之后,我想出了如何edit the scheme.在"运行"和"停止"按钮的右侧,有一个跳转条显示:ProjectName>Platform,在我的情况下是Flashlight>iPhone6.我点击了手电筒,显示了一个下拉列表Edit scheme.我点击Edit scheme,然后在下面Run/Debug,有一个复选框Enable Zombie Objects,我检查了.

你用调试符号编译了吗?

我猜不会.我读了一些Apple文档来弄清楚如何做到这一点:我点击Project Navigator的顶行,选择Build Settings,然后我向下滚动到Build Options,然后我选择了Build Variants,然后我点击箭头显示Debug和Release .在Debug我的右侧,我点击了normal,然后输入了debug.

我不确定那是做什么的.这样做之后我没有看到任何区别.

您是否在堆栈跟踪中找到了您的代码?

在堆栈跟踪区域中:

  1. 产品中心>简介
  2. 向下滚动窗口并选择Zombies.
  3. 然后单击红色"录制"按钮.
  4. 将出现Zombie Messaged弹出窗口.
  5. 在弹出窗口内,单击带有灰色圆圈的箭头.
  6. 在底部窗格中,单击Zombie行.
  7. 在右下方窗格的窗格顶部,选择最右侧的图标.

...列表中有一堆名称,前面有一个图标:

在此输入图像描述

一些图标是黑色的.如果我点击足够的黑色图标,我最终会跳转到我的代码.但这样做是有问题的,因为当我点击其中一个黑色图标时,很难回到堆栈跟踪列表来尝试另一个黑色图标.编辑:好的,我找到了一种解决这个问题的方法:当我点击Stack Trace窗格中的一个图标时,它会转到一些代码,其中一行会有一个指向它的红色箭头.如果我点击红色箭头,它会显示一个包含堆栈跟踪列表的弹出窗口,然后我可以点击其他一个黑色图标.

rma*_*ddy 7

仅仅因为对象的保留计数变为0并且dealloc调用其方法,并不意味着对象使用的内存会立即变为垃圾.解除分配的对象可能会在内存空间被重用于其他内容之前暂时保留在内存中.

这似乎就是这种情况.host在解除分配后调用日志会发现解除分配对象的内存仍然完好无损,因此访问其数据是有效的.

但是在Mac上的测试中似乎导致内存处理方式不同导致异常.