0
__block BOOL myBool = NO;
__strong MyClass *ptr = self;
self.footer.defaultSelectedItem.selectionBlock = ^{
    myBool = YES;
    ptr = nil;
};

This works just fine when my Scheme's Build Configuration is set to Debug, but I get an EXC_BAD_ACCESS when I run with Release. The EXC_BAD_ACCESS happens on the the following line

if(selectionBlock != nil) selectionBlock();

but if I comment out all the lines inside my selectionBlock then it runs with no error. Why does this run in Debug and not Release?

FYI I'm using Automatic Reference Counting (arc)

** EDIT in response to @RobNapier **

The original code that works in debug is:

__block BOOL flag = NO;
__strong EventsView *ptr = self;
self.footer.defaultSelectedItem.selectionBlock = ^{
    if(flag) return;
    flag = YES;
    [ptr backTUI:nil];
    flag = NO;
};
Jacksonkr
  • 31,583
  • 39
  • 180
  • 284
  • 1
    Can we assume from the presence of `__strong` that you're using ARC? – BJ Homer May 11 '12 at 16:11
  • Good point. Yes I'm using ARC. – Jacksonkr May 11 '12 at 16:21
  • 1
    What is "myObject = nil" here? Did you mean "ptr = nil"? From your other code, it looks like "myObject" is a class. – Rob Napier May 11 '12 at 16:26
  • What does the `selectionBlock` @property look like? – Firoze Lafeer May 11 '12 at 16:27
  • 1
    The code as written doesn't make a lot of sense, so I'm wondering if you've abstracted the right part of the code. As written (on the assumption that you meant `ptr=nil` in the block), the entire myBool would likely be optimized away since nothing reads it. I assume there's actually more going on inside this block? I'm guessing your use of `ptr` is to keep `self` from being deallocated until this block fires? This all feels very fragile. Since `self` isn't used in the block, it's not clear why that's important to you. You may need to expand the code a little. – Rob Napier May 11 '12 at 16:32
  • @RobNapier per your points of obvious failure on my part, I added the actual code. – Jacksonkr May 11 '12 at 17:15
  • Is your `selectionBlock` property copying the block? – Firoze Lafeer May 11 '12 at 17:31
  • @FirozeLafeer good question: `@property(nonatomic, copy) SelectionBlock selectionBlock;` – Jacksonkr May 11 '12 at 18:11

2 Answers2

1

There's no reason for the extra ptr here. Using self inside the block would be more correct. The block will retain self in that case. That may cause a retain loop, so it's up to you to remember to set self.selectionBlock = nil at some point before dealloc to break the retain loop.

flag may be optimized away here. It's not clear how it could possibly be useful from the above code.

I'm always very nervous about long indirection-chains in a set operation like this one:

self.footer.defaultSelectedItem.selectionBlock = ...

I would make sure that footer, and the current defaultSelectedItem can't disappear before this runs.

Simplify the problem. Make the block just log "Running block." Then add back things until it crashes.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • While all of this makes good sense, how is it that this works fine as is in debug mode, but not release mode? I see that I can optimize, but I don't see why this code is breaking just because of the mode change. – Jacksonkr May 11 '12 at 18:10
  • If your behavior relies on an undefined behavior (such as accessing something after it's been released), then it can easily work in debug but not release. – Rob Napier May 11 '12 at 19:37
  • I'm finding that it is definitely the code inside the selection block that is causing the problem. I'm confused because the `self` I'm referring to is actually the `superView` of the object that is running my block. So it makes no sense that the code thinks the `self` is not there. How would something like that happen? – Jacksonkr May 11 '12 at 21:30
  • Well, it could happen if this block of code ran after the superview was removed from the screen. But have you confirmed that `self` is the problem rather than one of the other lines? Have you tried my `NSLog()` test to validate that something that does not access variables still has trouble? – Rob Napier May 12 '12 at 00:48
0

For the life of me I could not get this to work with a block. So instead I moved to using a setter for the Event View pointer. I'm guessing that fixed the problem with my pointer by setting up an additional ARC retain. I'm still uncertain because I never saw a zombie get logged when using the block so yeah.

When in doubt, use a selector.

Jacksonkr
  • 31,583
  • 39
  • 180
  • 284