我有一个错误,我通过在Xcode中启用Scribble发现,修复错误不是问题,它没有以最好的方式实现,我可以删除整个块,但我不会&#39我明白为什么我首先得到这个问题,这告诉我我不明白的东西
如果我启用了Scribble,当它尝试在下面的代码中执行释放行时,它会崩溃而不会失败,
HDClipPlaybackController * theController = nil;
if( theSource != nil ) {
theController = [[HDClipPlaybackController alloc] initWithClipProxyList:theSource];
}
else {
theController = [[HDClipPlaybackController alloc] initWithClips:clips handles:[handles intValue]];
}
theController.startIndex = [startIndex intValue];
theController.completionHandler = ^(BOOL success){
theController.completionHandler = nil;
[theController release]; // <-- CRASH
};
[theController performSelectorInBackground:@selector(startDownloadingClips:) withObject:theController.clipProxyList.everyClipProxy];
线程1:EXC_BAD_ACCESS(代码= 1,地址= 0x55555555)
在发布行之前的行上添加一个断点并查看 theController 的值它是一个有效的对象地址但是踩到下一行我可以看到该值已更改为0x55555555( Scribble释放了它,我会认为该块的内存已被释放,因为我的理解是局部变量被复制到块作用域中,但这意味着块内存在被释放之前被释放完成执行?如果我只是将释放移到块外,崩溃就会消失,如果我启用Zombies而不是Scribble我也没有任何问题,所以它对我来说看起来不像是一个过度发布的问题。变量 theController 并不是__block声明的,所以如果我理解正确的话,它应该只是块范围内的一个更简单的指针。
这是一款运行32位的Mac OS X应用程序,包含Xcode 6.1.1和Mac OS 10.9.5。
答案 0 :(得分:1)
在theController.completionHandler = nil;
行上删除对块的最后一个引用,这会导致块被释放。然后在[theController release];
行上,访问块的theController
变量的捕获副本,该副本存储在块中。但是你已经释放了块,所以你正在访问一个已解除分配的字段。