Debugging EXC_BAD_ACCESS in AppKit - objective-c

I am receiving a EXC_BAD_ACCESS when calling setFrame on NSWindow. Unfortunately the exception occurs in AppKit where I can't debug it, in [NSWindow _setFrameCommon:display:stashSize:] with an invalid address of 0x40dedeadbec0 (the same every time).
The call in my code that causes the exception is in a subclass of NSWindow:
[super setFrame:frameRect display:flag];
Both frameRect and display are valid values, and self is a valid instance of my NSWindow subclass.
How should I go about debugging this error?

You need start debuging with enabling NSZombieEnabled. Fast of all NSWindow was released somewhere by some reasons. For example you have releaseWhenClose flag with YES value.
Error address which you provided seems like a Hexspeak

Related

EXC_BAD_ACCESS when closing NSDocument window (ARC enabled)

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.
After doing more research, the problem is still unsolved, but I have a clue:
Thank you for your response. Yes, I am at this point assuming it is a memory management issue. Is there way to track down the culprit? It doesn't seem like using Zombies in Instruments is helping: it points to a problem, but does not help me target the problem. That is, the offending line according to Instruments appears to be "-[NSApplication(NSWindowCache) _checkForTerminateAfterLastWindowClosed:saveWindows:]"; but I never issued that line. I have made what might be a little progress towards figuring things out.
The structure I am using in the document is:
NSDocumentController: default, not subclassed
NSDocument: subclassed, MyDocument; also the delegate of window
NSWindowController: default, not subclassed
NSWindow: MyDocument.xib, MainMenu.xib
I tried setting the delegate of the open window to nil as follows:
-(void)windowWillClose:(NSNotification *)notification
{
windowOpen = YES;
NSArray *windowControllers = [self windowControllers];
NSWindowController *currentWindowController = [windowControllers firstObject];
NSWindow *windowForCurrentController = [currentWindowController window];
NSDocument *w = [windowForCurrentController delegate];
[windowForCurrentController setDelegate:nil];
}
This causes the same crash.
Then, I thought perhaps the currentWindowController (or the application) was messaging a deallocated window. So I tried adding the line (at the end of the method above):
[currentWindowController setWindow:nil];
This gets rid of the crashes, but introduces new problems (such as when trying to load new files, etc.). But I'm wondering if this is a clue to help solve the overall problem.
The problem was that the app delegate was set to being MyDocument (the NSDocument subclass). The problem was solved by creating a standard AppDelegate class (NSObject, implementing the NSApplicationDelegate protocol), creating a corresponding NSObject in the XIB and setting it to type AppDelegate, and then making AppDelegate the delegate for MyDocument.
I seems that the source of the problem was that the MyDocument object was being deallocated, but it was still the delegate of the NSWindow subclass. The NSWindow then sent a dealloc message to the delegate, but it was already deallocated, causing a crash.
Here is the chain that solved it (long but instructive).

NSWindow closed its dealloc gets called still respondsToSelector Getting Called, and getting crashed on calling respondsToSelector:

I have developed Mac application, there is document is displayed from app delegate with addDocument , Now on close this nswindowcontroller's dealloc gets called, still repondsToSelector from other delegate methods like spilt view keeps hitting & as dealloc was called [super document] is null so respondsToSelector:]: message sent to deallocated instance . is there. Please can anyone help to solve this? How to completely release this document?

EXC_BAD_ACCESS (code=1, address=0x0) when runModalForWindow

I have a window and a window controller which opens when the user clicks a button.
Sometimes I get EXC_BAD_ACCESS(code=1, address=0x0).
0x7fff6f2a59e0: movq (%rax), %rdi
Here is the code:
ChooseProceduresWindowController *chooseProceduresWindowController = [[ChooseProceduresWindowController alloc] initWithWindowNibName:#"ChooseProceduresWindow"];
[NSApp runModalForWindow:[chooseProceduresWindowController window]];
The error appears then runModalForWindow: is called.
I don't get this error every time, but I couldn't find a pattern.
Thanks
the best way to debug EXC_BAD_ACCESS errors is to use NSZombies.
Check out this video for an explanation :
http://youtu.be/LQtPr8bkB3g
NSZombie keeps all your objects in memory when you are trying to release an object that has already been released, so you get closer to finding your bug. As #Mark H said, it is a memory management issue.
Also you could put an NSLog in your dealloc method to have a better idea of what is getting deallocated when at runtime.
That error will be thrown when the object doesn't exist in memory. I'd start looking for memory management issues. The first would be to make sure you are releasing the ChooseProceduresWindowController after using it.

Protecting my code from zombies from completion blocks

I'm familiar with the delegate pattern and nilling my delegates, especially when doing asynchronous calls which are still in progress when my view controllers disappear. I nil the delegate, and the callback successfully returns on a nil object.
I'm now experimenting with using completion blocks to make my code a little easier to read.
I call a network service from my view controller, and pass a block which updates my UITableView. Under normal circumstances it works fine. However, if I leave the view before it completes, the completion handler block is executed - but the UITableView is now a zombie.
Whats the usual pattern for handling this?
UPDATE WITH CODE SAMPLE
This is an iPad app, I have two view controllers on screen at once, like a split view. One is the detail, and the other is a grid of images. I click an image and it tell the detail to load the info. However, if i click the images too fast before they have chance to do the network call - I have the problems. On changing images the code below is called which counts the favourites of a image....
So here is my dilemma, if I use the code below - it works fine but it leaks in instruments if you switch images before the network responds.
If I remove the __block and pass in self, then it crashes with zombies.
I can't win... I'm sure i'm missing something fundamental about using blocks.
__block UITableView *theTable = [self.table retain];
__block IndexedDictionary *tableData = [self.descriptionKeyValues retain];
FavouritesController *favourites = [Container controllerWithClass:FavouritesController.class];
[favourites countFavouritesForPhoto:self.photo
completion:^(int favesCount) {
[tableData insertObject:[NSString stringWithFormat:#"%i", favesCount]
forKey:#"Favourites:" atIndex:1];
[theTable reloadData];
[tableData release];
[theTable release];
}];
Any tips? Thanks
SECOND UPDATE
I changed the way I loaded the favourites. Instead of the favourites being a singleton, I create an instance on each photo change. By replacing this and killing the old one - the block has nowhere to callback (i guess it doesn't even exist) and my code now just looks like the below, and it appear to be working:
[self.favourites countFavouritesForPhoto:self.photo
completion:^(int favesCount) {
[self.descriptionKeyValues insertObject:[NSString stringWithFormat:#"%i", favesCount]
forKey:#"Favourites:" atIndex:1];
[self.table reloadData];
}];
It doesn't leak, and doesn't appear to be crashing either.
I recommend you test that the tableview is not nil at the start of the block. It sounds like the tableview is properly discarded when its parent view goes off-screen, so after that point, no tableview operations are valid.
Retaining the UITableView within the block is a bad idea, because datasource/tableview updates can result in implicit method calls and notifications that will not be relevant if the tableview is not on-screen.
Block will retain any object that it references, except for those annotated with __block. If you want not to execute completion blocks at all, just make some property like isCancelled and check whether it is YES before calling completion block.
So you have a background operation which has to call back another object after it finishes and the object can be destroyed in the meantime. The crashes you describe happen when you have non retained references. The problem as you see is that the referred object goes away and the pointer is invalid. Usually, what you do is unregister the delegate inside the dealloc method so that the background task continues, and whenever it is ready to communicate the results back it says "Shoot, my callback object is nil", and at least it doesn't crash.
Still, handling manually weak references is tedious and error prone. You can forget to nil a delegate inside a dealloc method and it may go without notice for months before you encounter a situation where the code crashes.
If you are targeting iOS 5.0 I would read up upon ARC and the weak references it provides. If you don't want to use ARC, or need to target pre 5.x devices, I would recommend using zeroing weak reference libraries like MAZeroingWeakRef which work also for 3.x devices.
With either ARC's weak references or MAZeroingWeakRef, you would implement the background task with one of these fancy weak reference objects pointing back to your table. Now if the pointed object goes away, the weak pointer will nil itself and your background task won't crash.

Calling delegate method, unrecognized selector because sending to wrong object

In my app I do a lot of network loading. My data model consists of "Loader" objects that do this loading and call their delegate when finished/failed. The delegates all conform to a "LoaderDelegate" protocol.
The issue I'm having is that sometimes seemingly random objects, not the delegate, are getting the delegate messages. This of course causes a crash because of an unrecognized selector.
Only one set of crash logs tell me which one of my loaders is having the issue, the others don't have that information, just the random object that got the message.
I'm stuck at how to determine the real cause of this issue.
One set of crash logs has a loader trying to call it's delegate but reaching _UIImageViewExtendedStorage. Another has a loader is reaching __NSCFInputStream. Another __NSBlockVariable__. And yet another, CALayer.
And that's just in my latest beta from 3 days ago.
It would be one thing if it was the same object each time, but it seems almost random. Is it possible that memory is getting overritten with a new object somehow?
My delegate property for all of my loaders is an assign property, but the delegate is always alive when the loader finishes (delegates are my view controllers calling the loaders).
Please post some code, cause it is hard to troubleshoot. Remember to nil your delegate in the dealloc.
- (void) dealloc {
objectOfWhichIAmTheDelegate.delegate = nil;
}
What is more you the delegate should be an assign property not retain - but that's not a problem in your situation.
#property (assign) id<TheMightyDelegate> delegate;
Another thing you should do is to guarantee that the delegate responds to the selector you want to send to him before you fire the method.
if ([delegate respondsToSelector:#selector(yourMethod)]) {
[delegate performSelector:#selector(yourMethod)];
}
Hope this will put some light on your problem. If not please provide some code.
Turns out I was getting this error randomly all over the place, just not in this particular class and not just with delegate methods.
In my case, the problem turned out to be that I was accessing properties of various classes in multiple threads and those properties were nonatomic. Since I fixed that (removed nonatomic attribute of the properties), I haven't seen this happen anymore.