Crash: objc_retain in Mac App

I am seeing numerous reports of the following crash:


0  libobjc.A.dylib                0x7fffbf0eea31 objc_retain + 33
1  CoreFoundation                 0x7fffaa89046e +[__NSArrayI __new:::] + 110
2  CoreFoundation                 0x7fffaa8cbe25 -[__NSArrayM copyWithZone:] + 117
3  AppKit                         0x7fffa856ce9f -[NSMenu itemArray] + 62
4  AppKit                         0x7fffa88035fb -[NSPopUpButtonCell _autolayout_cellSize] + 208
5  AppKit                         0x7fffa863dda5 -[NSButton intrinsicContentSize] + 43
6  AppKit                         0x7fffa8fb5a2f __66-[NSView(NSConstraintBasedLayout) _generateContentSizeConstraints]_block_invoke + 31
7  AppKit                         0x7fffa868a9a9 +[NSAppearance _performWithCurrentAppearance:usingBlock:] + 79
8  AppKit                         0x7fffa85fe80f -[NSView(NSConstraintBasedLayout) _generateContentSizeConstraints] + 318
9  AppKit                         0x7fffa85fe288 -[NSView(NSConstraintBasedLayout) _updateContentSizeConstraints] + 467
10 AppKit                         0x7fffa85fe06b -[NSView updateConstraints] + 139


They occur while the app is in the background, usually after running a long time.


Is the issue the same as the one here: https://forums.developer.apple.com/message/130857 (poor memory management elsewhere in the app), or might there be a more specific cause? Any insight is appreciated.


Thanks

Replies

At a wild guess, I'd suggest that the NSButton is being overreleased somewhere. However, if your app is 100% Swift, or is Obj-C but 100% ARC, then it's kind of hard to overrelease anything directly.


One other possible cause of an overrelease is that the pointer to the NSButton (or any of the other objects implicated in the above backtrace) may refer to memory that was previously used for a different object. If any code had a reference that persisted after the lifetime of that object, it could happen that eventually a release occurs, but it now hits the object currently using the same memory. This kind of thing can be very hard to find.


Perhaps the key question is what changes when your app goes into the background? If you do anything special, I'd start looking there. If not, it may be a red herring (your app might be surviving in the foreground purely by luck).


The other area where it's easy to make a mistake is where a delegate object reference is unretained, but you don't realize that, and fail to provide for something to keep the delegate object alive.


Note that Swift is a bit more robust to these kinds of errors than Obj-C, and ARC is more robust than non-ARC. If you have any kind of mixed source app, then start by looking in the more dangerous places.

What QuinceyMorris said plus…

You should try running your app with zombies enabled. Bugs like this can be hard to find because there’s a big gap between the problem (the over-release) and the failure (this crash). Zombies helps to reduce that gap.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"