EXC_BAD_ACCESS when using recursive block

后端 未结 3 669
面向向阳花
面向向阳花 2020-12-30 13:14

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         


        
相关标签:
3条回答
  • 2020-12-30 14:09

    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.

    0 讨论(0)
  • 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!

    0 讨论(0)
  • 2020-12-30 14:19

    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;
    }
    
    0 讨论(0)
提交回复
热议问题