Incorrect codegen with ARC, a switch statement with blocks, and a captured block
| Originator: | michael.ash | ||
| Number: | rdar://11329693 | Date Originated: | 26-Apr-2012 05:09 PM |
| Status: | Closed | Resolved: | Duplicate |
| Product: | Developer Tools | Product Version: | |
| Classification: | Reproducible: |
Summary:
A switch statement containing a block which captures another block in the first case: will generate incorrect code for the second case:.
Steps to Reproduce:
Create a new iPhone project in Xcode, then put the following code into the app delegate:
id F(int x, void(^block)(void))
{
switch(x) {
case 0:
return ^{ return block; }();
case 1:
return nil;
}
return nil;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
F(1, ^{});
return YES;
}
Then run the app in the simulator.
Expected Results:
The app should run quietly.
Actual Results:
The app crashes with a stack trace like this:
* thread #1: tid = 0x1f03, 0x00375de3 libobjc.A.dylib`objc_release + 19, stop reason = EXC_BAD_ACCESS (code=2, address=0x1)
frame #0: 0x00375de3 libobjc.A.dylib`objc_release + 19
frame #1: 0x00002c1b ARCCrash`F + 203 at PLAppDelegate.m:22
frame #2: 0x00002d61 ARCCrash`-[PLAppDelegate application:didFinishLaunchingWithOptions:] + 97 at PLAppDelegate.m:28
frame #3: 0x0044d386 UIKit`-[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1292
frame #4: 0x0044e274 UIKit`-[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 524
frame #5: 0x0045d183 UIKit`-[UIApplication handleEvent:withNewEvent:] + 1027
frame #6: 0x0045dc38 UIKit`-[UIApplication sendEvent:] + 68
frame #7: 0x00451634 UIKit`_UIApplicationHandleEvent + 8196
frame #8: 0x01bd4ef5 GraphicsServices`PurpleEventCallback + 1274
frame #9: 0x014b0195 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
frame #10: 0x01414ff2 CoreFoundation`__CFRunLoopDoSource1 + 146
frame #11: 0x014138da CoreFoundation`__CFRunLoopRun + 2218
frame #12: 0x01412d84 CoreFoundation`CFRunLoopRunSpecific + 212
frame #13: 0x01412c9b CoreFoundation`CFRunLoopRunInMode + 123
frame #14: 0x0044dc65 UIKit`-[UIApplication _run] + 576
frame #15: 0x0044f626 UIKit`UIApplicationMain + 1163
frame #16: 0x00002b1d ARCCrash`main + 141 at main.m:16
Regression:
Unknown.
Notes:
The code in question works fine if the return statement in case 0: is surrounded by braces. By examining the generated assembly and comparing the broken case with the working case, it appears that the compiler is incorrectly generating cleanup code for the second case statement to clean up the block from the first case statement. Specifically, a call to objc_release is emitted for the case 1: code, which is unnecessary and is crashing when, it appears, it accesses stale or uninitialized data on the stack.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!
Got the same kind of crash
Seems like capturing any object (not necessarily a block) in a block is enough. I got the same behavior with a CALayer object.
I think I found something closely related.
http://stackoverflow.com/questions/9232705/exc-bad-access-when-i-scroll-my-view/10872089#10872089