I'm working on converting a document-based application from Garbage Collection (it ran fine under 10.6) to Automatic Reference Counting (trying to get it to compile and run for 10.12). I'm getting a consistent EXC_BAD_ACCESS when the last window is closed. Nothing is flagged by the static analyser.
I used Instruments to look for Zombies, and indeed there appears to be a `release` message sent to a deallocated object. Here is the trace:
# Event ∆ RefCt Timestamp Responsible Library/Responsible Caller
173 Release -1 3 00:05.226.677 Foundation __48-[NSFileAccessArbiterProxy removeFilePresenter:]_block_invoke
174 Release -1 2 00:05.226.679 Foundation -[NSFilePresenterXPCMessenger invalidate]
175 Retain +1 3 00:05.226.823 Foundation -[NSBlockOperation initWithBlock:]
176 Retain +1 4 00:05.226.858 AppKit -[NSDocument close]
177 Release -1 3 00:05.227.350 Foundation -[NSFilePresenterXPCMessenger dealloc]
Retain/Release (2) 00:05.227.484 AppKit -[NSDocumentController removeDocument:]
180 Release -1 2 00:05.227.485 AppKit -[NSDocumentController removeDocument:]
Retain/Release (2) 00:05.227.496 AppKit -[NSUIActivityManager addProvider:toUserActivity:withSetter:]
183 Autorelease 00:05.227.499 AppKit -[NSWindowController _windowDidClose]
184 Release -1 1 00:05.228.172 Foundation -[NSAutoreleasePool drain]
185 Release -1 0 00:05.228.184 Foundation -[NSBlockOperation dealloc]
186 Zombie -1 00:05.242.579 AppKit -[NSApplication(NSWindowCache) _checkForTerminateAfterLastWindowClosed:saveWindows:]
The difficult I am having in diagnosing this problem is that I can see the message being sent to the Zombie, but because I do not release any objects (it is all done by ARC), I'm guessing there is an implicit release going on somewhere. But I'm not sure where to look.
When in the debugger, `lldb` complains of a crash in `main.m` at:
return NSApplicationMain(argc, (const char **) argv);
Any help would be greatly appreciated. Thank you.
>> the NSDocument subclass gets deallocated when the last document closes […] Does that sound right?
I wouldn't have thought so, but maybe. Anyway, it sounds like a terrible idea to use it. How do you implement delegate methods? As class methods?
>> would it be appropriate to set the MainMenu.xib controller as my App delegate instead of my NSDocument subclass?
I'm not sure what object you mean by controller. The way it's usually done (usually == almost always) is to put the App delegate object into MainMenu.xib. It's just a custom subclass of NSObject that adopts NSApplicationDelegate protocol. (If you need to create it, drag in an "Object" item from the IB library, the blue cube, and change its class to match the app delegate class you define in code.) Then this custom object is connected, in the XIB, as the delegate of the NSApplication pseudo-object that's also in the XIB. That means your app delegate is created when the main menu NIB is instantiated, and never goes away. You don't need any code to set this up.
In fact, this structure is what you get from an Xcode template, you hardly ever have to set it up yourself. Maybe your app was originally created from a very old template, or someone went to the trouble of throwing away the in-XIB app delegate, or some other weird scenario.