【问题标题】:Printing an NSMutableArray causes crash with no error code打印 NSMutableArray 会导致崩溃且没有错误代码
【发布时间】:2011-06-08 12:38:42
【问题描述】:

我确定我的应用程序在以下行崩溃:

if(sourceValues != nil && [sourceValues class] == [NSMutableArray class])
    [sourceValues release];

"sourceValues" 在我的班级顶部被声明为 NSMutableArray。 “if”循环得到满足,并且 [sourceValues release] 调用被调用,这使程序崩溃,没有错误代码。所以,由于 sourceValues != nil 和 [sourceValues class] == [NSMutableArray class],我想看看 sourceValues 到底是什么。因此,在“if”循环之上,我添加了以下内容:

NSLog(@"sourceValues is %@", sourceValues);

但我的程序不会打印它。它只是在该行上没有错误代码而崩溃。所以,如果 sourceValue 存在并且如果它是 NSMutableArray,为什么它不会被打印出来。这里有什么问题?

我正在尝试编写“如果 sourceValues 已分配,则释放它”的代码。我该怎么做?

【问题讨论】:

  • 还有,sourceValues是怎么分配的?

标签: iphone objective-c memory nsmutablearray


【解决方案1】:

为什么不使用:

if(sourceValues != nil && [sourceValues isKindOfClass:[NSMutableArray class]])
    [sourceValues release];

您可能想使用其他方法,例如:

  • isMemberOfClass:

【讨论】:

  • 如果问题仍然存在,则说明问题与您的对象释放有关。您可能想向我们展示其余的代码。
  • 如果sourceValues 已经发布,那么对sourceValues 的任何测试都无济于事。
【解决方案2】:

如果这样……

NSLog(@"sourceValues is %@", sourceValues);

... 正在使您的程序崩溃,这是因为sourceValues 已经发布。无论你在哪里releasesourceValues,都设置为nil

[sourceValues release], sourceValues = nil;

如果您的应用仍然崩溃,那是因为该数组已在其他地方过度释放。也就是说,您没有正确平衡保留和释放。首先,尝试“构建和分析”并修复静态分析器识别的任何问题。接下来,打开僵尸检测并查看您首先向过度释放的对象发送消息的位置。

请注意,[sourceValues class] == [NSMutableArray class] 将不起作用,并且永远不应使用该模式来检查实例是否属于特定类。您应该始终使用isKindOfClass:isMemberOfClass:

但是,由于无论如何您都无法区分可变数组或不可变数组,因此首先检查是没有意义的。

【讨论】:

    【解决方案3】:

    首先,释放nil 对象没有危险。因此,“如果 sourceValues 已分配,则释放它”的问题。可能是多余的。除非您正在做一些时髦的事情,否则您应该遵循常规的内存管理规则,只需在 dealloc 中调用 [sourceValues release];

    您是否尝试过打开断点运行所有程序(Xcode 中的“构建和调试 - 断点打开”)?与通常的“构建并运行”相比,这通常会为您提供更多的调试信息。

    可能(我根据我过去遇到的一些奇怪问题猜测)您实际上已经释放了sourceValues,但指针仍然指向它的旧内存。如果发生这种情况,一个新对象可能位于程序将尝试将其视为 NSMutableArray 的那个区域。

    【讨论】:

    • 但我没有使用 dealloc。有没有办法只说“如果 X 已分配,释放它”
    • 你没有使用dealloc?这听起来像你做错了什么......释放从来没有真正“释放”任何内存。它只负责将保留计数降低1。如果保留计数达到0,则调用dealloc释放内存。
    • 为什么不直接发布呢?您可以将 release 发送到 nil 而不会产生不利影响。
    • 永远不应该有一行代码在数组上调用dealloc。如果他的班级没有dealloc,那当然是个问题,但[sourceValues dealloc]; 将是完全错误的(重申这一点)。
    • @bbum 是的,当然 :) 如果您使用的是 Objective C,“我没有使用 dealloc”根本不正确,因为它是自动调用的。
    【解决方案4】:

    尝试检查retainCount,例如:

    NSLog(@"保留计数:%d", [sourceValues retainCount]);

    仅用于测试/调试,不要在 if 语句中依赖它。

    另外,您可以尝试迭代 sourceValues 并将其内容打印到 NSLog,但我不知道里面有什么。

    最好的办法是将类属性设置为带有 RETAIN 的 MSMutableArray,并使用综合。 dealloc 将负责释放。

    如果上面实现了,可以alloc/init如下:

    self.sourceValues = [[[NSMutableArray alloc] init] autorelease];
    

    然后根据需要将对象直接添加到 self.sourceValues。释放不用担心,会在dealloc中完成。

    【讨论】:

    • 自动释放不适用于我正在使用的设置。我没有使用 dealloc 来清除事物。
    • 为什么不使用dealloc?不要让自己变得更难;)
    • -retainCount 不应使用。甚至不用于调试。
    • @tbone 你应该永远直接致电dealloc。不是。曾经。 (以防笑话丢失)
    • @everyone:如果 tbone 为他的一方辩护,那么就收回他的 -1 票。
    猜你喜欢
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    相关资源
    最近更新 更多