Finding the source of Cocoa/ObjC exceptions

Discussion in 'Mac Programming' started by gekko513, Mar 23, 2006.

  1. gekko513 macrumors 603


    Oct 16, 2003
    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?
  2. caveman_uk Guest


    Feb 17, 2003
    Hitchin, Herts, UK
    I generally end up putting a load of NSLog()s and NSAsserts in to find out. I guess there must be a better way.
  3. gekko513 thread starter macrumors 603


    Oct 16, 2003
    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:
    @interface ZWindow : NSWindow {
    @implementation ZWindow
    - (void)makeKeyAndOrderFront:(id)sender {
    	NSLog(@"%s", __PRETTY_FUNCTION__);
    	[super makeKeyAndOrderFront:sender];
    @implementation SomeClassThatIUseInTheNib
    + (void) initialize {
    	[ZWindow poseAsClass:[NSWindow class]];
    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.
  4. gekko513 thread starter macrumors 603


    Oct 16, 2003
    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.

Share This Page