这是我的第一篇文章。我为错误道歉。
我有一个可以修复的崩溃,但我不明白为什么它首先会崩溃。我试图将代码简化为使其崩溃的基本要素:
GCFTile *currentTile;
NSInteger repeatCount = 0;
do {
currentTile = self.remainingTilesArray[0];
if (repeatCount == 0) {
[self.remainingTilesArray removeObjectAtIndex:0];
[self.remainingTilesArray addObject:currentTile];
}
void (^myBlock)() = ^{
currentTile;
};
repeatCount++;
} while (repeatCount == 1);
我正在使用 Xcode 4.5.2、iOS 5、ARC。此外,仅当 LLVM 编译器优化设置为“快速”或更高时,它才会崩溃。
上面的代码将从 NSMutableArray 中获取和删除一个对象,将其放回原处,然后从数组中获取另一个对象。上面的代码将运行而不会崩溃,但是如果我稍后扫描数组中的所有元素(例如,从不同的方法),那么它就会崩溃。看起来随机内存地址被添加到数组中(可能来自上面对 addObject 的调用)。
上面的块应该什么都不做,但如果我改变它,那么以后就不会崩溃了。(例如,空块 = 没有崩溃。不要将块声明为“myBlock” = 没有崩溃。)如果我不重复循环,就没有崩溃。如果我不重新添加对象,则不会发生崩溃。如果我使用 __block 或在 do 循环中声明 currentTile,则不会发生崩溃。
我知道块是“堆栈本地的”,但这个块没有做任何事情!它运行良好,无需编译器优化。
知道发生了什么吗?
编辑(12-5-12):有人要求提供崩溃日志。我正在模拟器中运行,所以我不知道如何获得它。但这里有一些来自 Debug Navigator 的内容:
#0 0x0140409b in objc_msgSend ()
#1 0x00010931 in __33-[GCFGame checkThatTilesAreValid]_block_invoke_0 at /Users/geoffrey2/personal/projects/Color Fever/Color Fever/GCFGame.m:54
#2 0x01cb24a5 in __NSArrayEnumerate ()
#3 0x01cb2026 in -[NSArray enumerateObjectsWithOptions:usingBlock:] ()
#4 0x01cb1f35 in -[NSArray enumerateObjectsUsingBlock:] ()
#5 0x000108f6 in -[GCFGame checkThatTilesAreValid] at /Users/geoffrey2/personal/projects/Color Fever/Color Fever/GCFGame.m:52
并且主窗口显示了这一点(加上更多行):
libobjc.A.dylib`objc_msgSend:
0x140408c: movl 8(%esp), %ecx
0x1404090: movl 4(%esp), %eax
0x1404094: testl %eax, %eax
0x1404096: je 0x14040e8 ; objc_msgSend + 92
0x1404098: movl (%eax), %edx
0x140409a: pushl %edi
0x140409b: movl 8(%edx), %edi
错误是EXC_BAD_ACCESS(code=2, adddress=0x9).