Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Crash in actionForLayer:forKey:

I have a cryptic EXC_BAD_ACCESS when changing some UILabel's frame. The crash is random, usually I have to repeat the conditions for several minutes.

Enabling NSZombies, as well as other memory debug flags (NSDebugEnabled, MallocStackLogging), doesn't help, the crash stills stays as opaque : just a BAD_ACCESS with no message in the console. The target seems correct and alive, so it doesn't look like a deallocated memory problem.

To get some more info, I subclassed UILabel and rewrote the crashing function :

@implementation TestUILabel
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event {
    return [super actionForLayer:layer forKey:event];
}
@end

It crashes in the super's method, but on inspection everything seems correct (printing retainCount for 'self' and 'layer' gives respectively 3 and 2) :

(gdb) po self

< TestUILabel: 0x6ac2800; baseClass = UILabel; frame = (173 174; 0 0); text = '54 m²'; opaque = NO; autoresize = LM+TM; autoresizesSubviews = NO; userInteractionEnabled = NO; animations = { position=< CABasicAnimation: 0xe07ba60>; }; layer = < CALayer: 0xbf1b950>>

(gdb) po event

bounds

(gdb) po layer

< CALayer:0xbf1b950; position = CGPoint (173 174); bounds = CGRect (0 0; 0 0); delegate = < TestUILabel: 0x6ac2800; baseClass = UILabel; frame = (173 174; 0 0); text = '54 m²'; opaque = NO; autoresize = LM+TM; autoresizesSubviews = NO; userInteractionEnabled = NO; animations = { position=< CABasicAnimation: 0xe07ba60>; }; layer = < CALayer: 0xbf1b950>>; contents = < CGImage 0xe04ed60>; opacity = 1; animations = [position=< CABasicAnimation: 0xe07ba60>]>

Did someone get a similar problem ? Or have any ideas where this could come from ?

Thanks in advance !

Edit: here's the complete crash backtrace :

Thread 1, Queue :
com.apple.main-thread
#0 0x00459b2c in -[UIView(CALayerDelegate) actionForLayer:forKey:] ()
#1 0x00eaaac7 in -[CALayer actionForKey:] ()
#2 0x00ea80fe in actionForKey(CALayer*, CA::Transaction*, NSString*) ()
#3 0x00ea8066 in beginChange(CALayer*, CA::Transaction*, unsigned int, objc_object*&) ()
#4 0x00eaba3a in CALayerSetPosition(CALayer*, CA::Vec2 const&, bool) ()
#5 0x00eab8b5 in -[CALayer setPosition:] ()
#6 0x00eab7cc in -[CALayer setFrame:] ()
#7 0x0045739d in -[UIView(Geometry) setFrame:] ()
#8 0x00542a68 in -[UILabel setFrame:] ()
#9 0x0000a97f in -[MosaicElementView setupWithAdvert:] at /Users/eino/Prog/AJ/Classes/Search/SubViews/MosaicElementView.m:30
#10 0x00079cb9 in -[SearchResultsViewController setupElement:withCell:indexPath:actualIndex:] ()
#11 0x000797a2 in -[SearchResultsViewController tableView:cellForRowAtIndexPath:] ()
#12 0x004957fa in -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] ()
#13 0x0048b77f in -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] ()
#14 0x004a0450 in -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] ()
#15 0x00498538 in -[UITableView layoutSubviews] ()
#16 0x00eb0451 in -[CALayer layoutSublayers] ()
#17 0x00eb017c in CALayerLayoutIfNeeded ()
#18 0x00ea937c in CA::Context::commit_transaction(CA::Transaction*) ()
#19 0x00ea90d0 in CA::Transaction::commit() ()
#20 0x00ed97d5 in CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) ()
#21 0x017e9fbb in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ ()
#22 0x0177f0e7 in __CFRunLoopDoObservers ()
#23 0x01747bd7 in __CFRunLoopRun ()
#24 0x01747240 in CFRunLoopRunSpecific ()
#25 0x01747161 in CFRunLoopRunInMode ()
#26 0x01e7d268 in GSEventRunModal ()
#27 0x01e7d32d in GSEventRun ()
#28 0x0043042e in UIApplicationMain ()
#29 0x000021fe in main at /Users/eino/Prog/AJ/main.m:11

The crasing line from frame 9 is basically just the frame change :

labelPrice.frame = rect;

with rect being a correct CGRect (106, 143, 86, 22).

like image 772
Eino Gourdin Avatar asked Jun 17 '11 10:06

Eino Gourdin


2 Answers

You probably already checked for this, but it's worth shot...

Are you certain that you aren't doing anything that would effect any UI elements in a background thread? Perhaps you're doing some computation related to this search and it changes a property of some view.

I have seen his sort of thing in cases where I forgot a performSelectorOnMainThread:withObject:waitUntilDone: call and then altered the UI in the background.

like image 176
David Hodge Avatar answered Nov 18 '22 22:11

David Hodge


This crash has non-main threads that appear to use UIKit classes or functions. Generally speaking, it is only safe to use UIKit from the main thread. Calling into UIKit from background threads can cause unpredictable behavior (like crashes!). Please double check that all of your code (that is not on the main thread) has been explicitly marked as safe to use in the background by Apple.

External resources:

UIKit Framework Reference

like image 1
Qun Li Avatar answered Nov 18 '22 22:11

Qun Li