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 (^Bl
You seem to be adding squares
to the array while traversing the array. 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.
You need a __block
on Block
, change the declaration to:
__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. In your code Block
hasn't yet been given a value, as you are constructing the block in the assignment...
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.
I don't know why its worked at all for you without the __block
- failed straightaway for me. With the modifier however I can recurse to at least a depth of 10,000 - so stack space isn't a problem!
You're liking doing something wrong with the setup -- your Square
objects are probably messed up somehow. 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;
}