Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

gekko513

macrumors 603
Original poster
Oct 16, 2003
6,301
1
Is there an easy way of finding out where a Cocoa exception, such as "*** -[NSCFDictionary setObject:forKey:]: attempt to insert nil value", originates from?

By where I mean which method in my own code made the offending call to NSCFDictionary. I'm not even sure if this is really an exception or if it's just an error log.

Is it possible to make a conditional breakpoint in methods that are in the imported frameworks?

Or can I create a proxy method to catch calls and then forward them, so that I can put up a breakpoint in the proxy method instead?
 

gekko513

macrumors 603
Original poster
Oct 16, 2003
6,301
1
For those interested in an update on this: I found the offending method call, but not as easily as I would like.

I did, however, discover the "poseAs" feature in Objective C, a useful debugging trick in general although it didn't work as elegantly as I had hoped in this case.

PoseAs lets a subclass pose as it's super-class. This can among other things be used to add logging messages or breakpoints in classes that you haven't implemented yourself.

I first wanted to do that for NSCFDictionary, but I couldn't find a .h file with the interface for it, so I had to settle for NSMutableDictionary, which I assume use the NSCFDictionary and causes the error. I tried this and I was able to log calls to setObject:forKey:, but I still wasn't able to find the error.

Then I decided to try from another angle. I knew the error occured when makeKeyAndOrderFront: was called on my Preferences windows. I didn't know how to put a breakpoint there and step through to see exactly where the error occured, but this problem could easily be solved by "poseAs".

In SomeClassThatIUseInTheNib.m I added:
Code:
@interface ZWindow : NSWindow {
}
@end
@implementation ZWindow
- (void)makeKeyAndOrderFront:(id)sender {
	NSLog(@"%s", __PRETTY_FUNCTION__);
	[super makeKeyAndOrderFront:sender];
}
@end

@implementation SomeClassThatIUseInTheNib
+ (void) initialize {
	[ZWindow poseAsClass:[NSWindow class]];
}
<snip>
This let me put a breakpoint on makeKeyAndOrderFront: and I was able to step through and eventually find the cause for the error.

I would still be happy if anyone could tell me an easier way of doing this.
 

gekko513

macrumors 603
Original poster
Oct 16, 2003
6,301
1
OK, even though I found the bug I wasn't quite happy with not having a decent way of tracking down a similar bug in the future so I investigated further and I found a better way.

First: Add a symbolic breakpoint (in the breakpoints window in the debugger) at -[NSCFDictionary setObject:forKey:]

This isn't very helpful in itself because that method is called millions of times, but you get to see what happens in that method (sort of, most of it is in assembly), and I figured that the function call _NSDictionaryRaiseInsertNilValueException was the one I really wanted to break at:

Second: Add a symbolic breakpoint at _NSDictionaryRaiseInsertNilValueException, then disable the first breakpoint.

That's it.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.