使用CFRelease释放的对象会导致明显的崩溃,但很少发生

时间:2012-03-05 18:04:20

标签: objective-c ios crash

我有以下方法:

+ (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]似乎可以修复错误,这对我来说很有意义。

3 个答案:

答案 0 :(得分:5)

仅仅因为一块内存被释放并且被释放并不意味着它立即返回到操作系统。您的应用程序可以根据多种因素和多个层次在任意时间段内保留它。操作系统有时会做更重要的事情,而不是回收你放弃的每一块内存,并且可能会在半秒内再次询问。访问您称为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感兴趣了解更多关于这个话题。

答案 1 :(得分:2)

CFRelease参数不能为NULL。

  

如果CFRelease参数为NULL,则会导致运行时错误   你的申请将崩溃

if(md5hash)
CFRelease(md5hash);

答案 2 :(得分:0)

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

如果您需要在任何时间内保持返回值,请确保将其保留在调用者中。