EXC_BAD_ACCESS inside [UILabel drawRect]

0

I get EXC_BAD_ACCESS inside [UILabel drawRect] and sometimes inside [UILabel setText]. The problem occurs on the hardware device and in Simulator.

I haven't overwritten the drawRect: method, nor did I do anything else special with the UILabel class. The label is created through a storyboard.

I've examined this with NSZombiesEnabled and then I get one of these messages shortly before the debugger suspends the execution:

2014-04-22 20:35:42.032 AppName[5621:a0b] *** -[CFString length]: message sent to deallocated instance 0x1191c730

2014-04-22 20:33:43.447 AppName[5607:a0b] *** -[NSConcreteMutableAttributedString length]: message sent to deallocated instance 0x12a58760

The UILabel's text is changed a lot of times (maybe 50 times per second).

Here is the complete stack trace where the debugger stopped after the above CFString error message was printed:

#0  0x03619811 in ___forwarding___ ()
#1  0x036194ee in _CF_forwarding_prep_0 ()
#2  0x00f38183 in -[NSConcreteMutableAttributedString length] ()
#3  0x00efe25f in -[NSAttributedString enumerateAttributesInRange:options:usingBlock:] ()
#4  0x014c1dea in -[NSAttributedString(UILabelAdditions) _ui_synthesizeAttributedSubstringFromRange:usingDefaultAttributes:] ()
#5  0x014c2d89 in -[UILabel _synthesizedAttributedText] ()
#6  0x014c84da in -[UILabel _drawTextInRect:baselineCalculationOnly:] ()
#7  0x014c7b94 in -[UILabel drawTextInRect:] ()
#8  0x014c9b0e in -[UILabel drawRect:] ()
#9  0x01381d56 in -[UIView(CALayerDelegate) drawLayer:inContext:] ()
#10 0x00c0fdc9 in -[CALayer drawInContext:] ()
#11 0x00c0fcfa in backing_callback(CGContext*, void*) ()
#12 0x00b00cf4 in CABackingStoreUpdate_ ()
#13 0x00c0fc92 in ___ZN2CA5Layer8display_Ev_block_invoke ()
#14 0x00c43b23 in x_blame_allocations ()
#15 0x00c0fafd in CA::Layer::display_() ()
#16 0x00c0fd49 in -[CALayer _display] ()
#17 0x00c0f506 in CA::Layer::display() ()
#18 0x00c0fd23 in -[CALayer display] ()
#19 0x00c03ed3 in CA::Layer::display_if_needed(CA::Transaction*) ()
#20 0x00c03f4c in CA::Layer::layout_and_display_if_needed(CA::Transaction*) ()
#21 0x00b6bae6 in CA::Context::commit_transaction(CA::Transaction*) ()
#22 0x00b6ce71 in CA::Transaction::commit() ()
#23 0x00c38aea in CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) ()
#24 0x00c38f6b in CA::Display::TimerDisplayLink::callback(__CFRunLoopTimer*, void*) ()
#25 0x035e7bd6 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ()
#26 0x035e75bd in __CFRunLoopDoTimer ()
#27 0x035cf628 in __CFRunLoopRun ()
#28 0x035ceac3 in CFRunLoopRunSpecific ()
#29 0x035ce8db in CFRunLoopRunInMode ()
#30 0x035549e2 in GSEventRunModal ()
#31 0x03554809 in GSEventRun ()
#32 0x01317d3b in UIApplicationMain ()
#33 0x00002f0d in main at (I've cut the path to the project's home.)/main.m:18
#34 0x02d98725 in start ()

Why does this error take place? What to do about it?

Wild guess: Do I have to access UILabel somehow in a thread-safe manner?

UPDATE:

The code where the text is changes is this:

- (void)updateTimeLabels:(NSTimeInterval)timeInterval {
    NSDate *timeIntervalDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
    NSString *timeIntervalStr = [_TIME_FORMATTER stringFromDate:timeIntervalDate];
    NSString *timeSecondfractionStr = [_SECONDFRACTION_FORMATTER stringFromDate:timeIntervalDate];

    if (![NSThread isMainThread]) { // i've added these 3 lines for checking
        NSLog(@"%s: not on the main thread", __FUNCTION__); // I have not observed this being printed ever
    }

    self.timeCodeLabel.text = timeIntervalStr; // this is the line where sometimes the error takes place
    self.timeCodeSecondfractionLabel.text = timeSecondfractionStr;
}
ios
objective-c
uilabel
exc-bad-access
asked on Stack Overflow Apr 22, 2014 by Daniel S. • edited Apr 22, 2014 by Daniel S.

1 Answer

3

The error indicates that your label has been deallocated and you are trying to send a message to a dead object (a zombie.)

That could happen - I guess - if you were trying to set the label text from a background thread, but probably not.

It's more likely that you are over-releasing the label (manual reference counting) or have not kept a strong reference to it (ARC) so it's being released. Please post code about the lifecycle of your label objects. How are they being created? Are you adding your labels as subviews of the current view controller's content view? Are you keeping strong references to the labels?

If you're using manual reference counting, how are you handling the labels' lifecycles?

answered on Stack Overflow Apr 22, 2014 by Duncan C

User contributions licensed under CC BY-SA 3.0