Y Robin
Y Robin

Reputation: 80

Block in MRC why this code not crash

File Person.h

@interface Person:NSObject
+ (void)callBlock:(void (^)())block;
@end

File Person.m

@imp:
+ (void)callBlock:(void (^)())block
{ 
   [NSThread sleepForTimeInterval:2];
   block();
}
@end

Code in ViewDidLoad:

Person *p = [[Person alloc] init];
void (^block)() = ^{
NSLog(@"%@",p);
  [p release];
}
[Person callBlock:block];

finish!

MyQuestion:

  1. in main function, block var is a stackblock,and this block assign to the function +callBlock:,and the block in Person.m is also a stackblock. Content of them are same.

  2. In my opinion,the block in main will be free by system before called in Person.m, so I think this program will crash, but it run normal. why?

  3. And i think my code is same as below.

...

 void example_addBlockToArray(NSMutableArray *array) {
   char b = 'B';
   [array addObject:^{
      printf("%cn", b);
   }];
 }

 void example() {
      NSMutableArray *array = [NSMutableArray array];
      example_addBlockToArray(array);
      void (^block)() = [array objectAtIndex:0];
      block();
    }

This programe crashed! which the difference between them?

Sorry! both program use mrc!!! i did not write clearly!

Upvotes: 1

Views: 177

Answers (3)

Alex Posplaw
Alex Posplaw

Reputation: 116

As it seems, you're using manual memory management.

Therefore is an explanation:

Person object case

  1. You create the object
  2. You create the block
  3. You call the block
  4. Block logs the object out
  5. Block frees the object That's why there is no crash

Char log case

Since you're not using ARC, it goes this way:

  1. You add the block that logs char
  2. Once you leave the function that adds the block to an array, the char you've just created is going to be released from memory. In case if you use ARC for memory management, it will keep this char alive in the memory, until this block exists. But once you remove it from an array and block's reference count equals to 0, this char also being released.
  3. You take a block from an array
  4. Call it, it references to a memory address of char that already released, crash appears. As explained in your error: EXC_BAD_ACCESS (code=1, address=0x0) Means, that you point to zero address (null pointer exception in other words).

So, that's it.

Upvotes: 2

Avi
Avi

Reputation: 7552

As pointed out in the comments, the first example does not crash because the block is defined in a function scope which doesn't end until after the block is called.

The second example, on the other hand, defines the block in a secondary function, which ends before the block is called. Thus, at the time of the block invocation, the stack has already been modified and the block has become invalid.

Upvotes: 1

rose
rose

Reputation: 241

After main function executed the block in main will be free by system ,not before called in Person.m. I tried the second code in viewcontroller, it works fine, not crash.

Upvotes: 0

Related Questions