[英]EXC_BAD_ACCESS when using recursive block
I'm trying to create recursion using blocks. 我正在尝试使用块创建递归。 It works for a while, but eventually it crashes and gives me a bad access exception.
它工作了一段时间,但最终它崩溃并给我一个糟糕的访问异常。 This is my code:
这是我的代码:
BOOL (^Block)(Square *square, NSMutableArray *processedSquares) = ^(Square *square, NSMutableArray *processedSquares) {
[processedSquares addObject:square];
if (square.nuked) {
return YES; // Found a nuked square, immediately return
}
for (Square *adjacentSquare in square.adjacentSquares) {
if ([processedSquares containsObject:adjacentSquare]) {
continue; // Prevent infinite recursion
}
if (Block(adjacentSquare, processedSquares)) {
return YES;
}
}
return NO;
};
__block NSMutableArray *processedSquares = [NSMutableArray array];
BOOL foundNukedSquare = Block(square, processedSquares);
Explanation: I have a Square
class that has a BOOL nuked
. 说明:我有一个具有BOOL
nuked
的Square
类。 It also has an NSArray adjacentSquares
containing other Squares. 它还有一个NSArray
adjacentSquares
的广场包含其他广场。
I want to check whether a square, or one of its 'connected' squares, is nuked or not. 我想检查一个正方形或其中一个“连接”方块是否被核化。
The array processedSquares
is to keep track of the squares I have checked to prevent infinite recursion. 数组
processedSquares
用于跟踪我检查过的方块,以防止无限递归。
When I run this, it's doing a lot of calls of this block (as expected). 当我运行它时,它正在执行此块的大量调用(如预期的那样)。 But at some point, it crashes at the last line with a bad access exception.
但在某些时候,它在最后一行崩溃并出现访问异常。
I also get this in the console: 我也在控制台中得到这个:
Cannot access memory at address 0x1
无法访问地址0x1处的内存
Cannot access memory at address 0x1无法访问地址0x1处的内存
Cannot access memory at address 0x1无法访问地址0x1处的内存
Cannot access memory at address 0x1无法访问地址0x1处的内存
warning: Cancelling call - objc code on the current thread's stack makes this unsafe.警告:取消当前线程堆栈上的调用 - objc代码会使其不安全。
I'm not that familiar with blocks and recursion. 我对块和递归并不熟悉。 Any ideas?
有任何想法吗?
As requested, the backtrace: 根据要求,回溯:
#0 0x00000001 in ??
#1 0x000115fb in -[Square connectedToNukedSquare] at Square.m:105
#2 0x00010059 in __-[Bot makeMove]_block_invoke_1 at Bot.m:94
#3 0x91f3f024 in _dispatch_call_block_and_release
#4 0x91f31a8c in _dispatch_queue_drain
#5 0x91f314e8 in _dispatch_queue_invoke
#6 0x91f312fe in _dispatch_worker_thread2
#7 0x91f30d81 in _pthread_wqthread
#8 0x91f30bc6 in start_wqthread
You need a __block
on Block
, change the declaration to: 您需要在
Block
上使用__block
,将声明更改为:
__block BOOL (^Block)(Square *square, NSMutableArray *processedSquares);
Block = ^(Square *square, NSMutableArray *processedSquares) {
When a variable ( Block
) is referenced within a block then its current value is copied into the block. 当在
Block
中引用变量( Block
)时,其当前值被复制到块中。 In your code Block
hasn't yet been given a value, as you are constructing the block in the assignment... 在你的代码
Block
还没有给出一个值,因为你在赋值中构造了块...
The __block
prefix passes the variable by reference - by the time your block makes its recursive call Block
has a value, the reference to it is used to obtain that value, and the recursive call is OK. __block
前缀通过引用传递变量 - 当块进行递归调用时Block
有一个值,对它的引用用于获取该值,递归调用是正常的。
I don't know why its worked at all for you without the __block
- failed straightaway for me. 我不知道为什么它在没有
__block
情况下为你工作 - 对我来说失败了。 With the modifier however I can recurse to at least a depth of 10,000 - so stack space isn't a problem! 然而,使用修饰符,我可以递归至少10,000的深度 - 因此堆栈空间不是问题!
You're liking doing something wrong with the setup -- your Square
objects are probably messed up somehow. 你喜欢设置错误 - 你的
Square
对象可能会以某种方式搞砸了。 Here's a complete example that works fine for me, maybe it can help you find your mistake: 这是一个适合我的完整示例,也许它可以帮助您找到错误:
#include <stdio.h>
#include <Foundation/Foundation.h>
@interface Square : NSObject
{
BOOL nuked;
NSArray *adjacentSquares;
}
@property(nonatomic) BOOL nuked;
@property(nonatomic, retain) NSArray *adjacentSquares;
@end
@implementation Square
@synthesize nuked;
@synthesize adjacentSquares;
@end;
BOOL (^Block)(Square *square, NSMutableArray *processedSquares) = ^(Square *square, NSMutableArray *processedSquares) {
[processedSquares addObject:square];
if (square.nuked) {
return YES; // Found a nuked square, immediately return
}
for (Square *adjacentSquare in square.adjacentSquares) {
if ([processedSquares containsObject:adjacentSquare]) {
continue; // Prevent infinite recursion
}
if (Block(adjacentSquare, processedSquares)) {
return YES;
}
}
return NO;
};
int main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Square *s1, *s2;
s1 = [[Square alloc] init];
s2 = [[Square alloc] init];
s1.adjacentSquares = [NSArray arrayWithObjects:s2, nil];
s2.adjacentSquares = [NSArray arrayWithObjects:s1, nil];
__block NSMutableArray *processedSquares = [NSMutableArray array];
BOOL foundNukedSquare = Block(s1, processedSquares);
printf("%d\n", foundNukedSquare);
[s1 release];
[s2 release];
[pool release];
return 0;
}
You seem to be adding squares
to the array while traversing the array. 您似乎在遍历数组时向数组添加
squares
。 I'm speaking of this line: 我说的是这句话:
[processedSquares addObject:square];
Might that have to do with it? 可能与它有关吗? You're adding an object while traversing.
您在遍历时添加了一个对象。 I'm surprised that this works at all.
我很惊讶这一点都有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.