【问题标题】:Object released with CFRelease causes obvious crash, but only rarely使用 CFRelease 释放的对象会导致明显的崩溃,但很少见
【发布时间】:2012-03-06 03:18:14
【问题描述】:

我有以下方法:

+ (NSString*) getMD5HashFromFile:(NSString*)filePath {
    CFStringRef md5hash = FileMD5HashCreateWithPath((CFStringRef)filePath, FileHashDefaultChunkSizeForReadingData);
    NSString *hashStr = (NSString*)md5hash;
    CFRelease(md5hash);
    return hashStr;
}

我在模拟器上遇到随机崩溃,大约每 20-30 次执行中就有 1 次。这不一致的事实并没有帮助我更深入地挖掘。

现在我再次看到代码,很明显md5hash 在返回之前被释放,这意味着返回的对象无效。返回的值以一致的方式在另一个方法中使用,有时会崩溃,但并非总是如此。我的问题是为什么这种情况很少发生,而且并不总是发生。

这与 Obj-C 和 C 代码的混合以及自动释放池的工作方式有关吗?

注意:该错误似乎已通过使用 NSString *hashStr = [NSString stringWithString:(NSString*)md5hash] 修复,这对我来说完全有意义。

【问题讨论】:

    标签: objective-c ios crash


    【解决方案1】:

    仅仅因为一块内存被释放和释放并不意味着它会立即返回给操作系统。您的应用程序可以根据众多因素和多个层次在任意时间段内保留它。操作系统有时要做的事情比回收你释放的每一块内存更重要,并且可能会在半秒内再次请求。访问您已调用 free() 但技术上拥有的内存不会产生信号。这就是MallocScribble 存在的原因。它会用垃圾 (0x55) 覆盖您释放的内存,以便在您使用释放的内存时更加明显。

    尝试以下方法:

    char *foo = malloc(100);
    strcpy(foo, "stuff");
    free(foo);
    printf("%s", foo);
    

    尽管完全错误,但大多数情况下都可以正常工作。现在,编辑您的 Scheme>Diagnostics 并启用 Scribble。重新运行,您会看到一堆“U”(0x55),表示您正在阅读废话。但它仍然不会崩溃。

    您可能对 Matt Gallagher 的 A look at how malloc works on the Mac 感兴趣,了解更多关于该主题的信息。

    【讨论】:

    • 谢谢罗伯。我认为这是一个很好的解释。实际上,现在我看到它写了,我不明白我已经是新的了。显然不够好:) 再次感谢
    • 我们都忘记了我们认为应该记住的东西 :D twitter.com/#!/cocoaphony/status/174989186032603136
    【解决方案2】:

    CFRelease 参数不能为 NULL。

    如果 CFRelease 参数为 NULL,这将导致运行时错误并且 你的应用程序会崩溃

    if(md5hash)
    CFRelease(md5hash);
    

    【讨论】:

      【解决方案3】:
      +(NSString*) getMD5HashFromFile:(NSString*)filePath {
          CFStringRef md5hash = FileMD5HashCreateWithPath((CFStringRef)filePath, FileHashDefaultChunkSizeForReadingData);
          NSString *hashStr = [(NSString*)md5hash copy];
          CFRelease(md5hash);
          return [hashStr autorelease];
      }
      

      如果您需要在调用方中保持任何时间长度,请确保在调用方中保留返回值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-31
        • 2011-08-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多