Once again, the XCODE debugger not only failed to help but got in the way by showing me a stack trace that was not directly relevant to my problem. The program crashed with EXC_BAD_ACCESS and the stack trace looked like this:
#0 0x90a594c7 in objc_msgSend
#1 0xbffff7b8 in ??
#2 0x932899d8 in loadNib
#3 0x932893d9 in +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:]
#4 0x9328903a in +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:]
#5 0x93288f7c in +[NSBundle(NSNibLoading) loadNibNamed:owner:]
#6 0x93288cc3 in NSApplicationMain
#7 0x00009f80 in main at main.mm:17
This made me think that my NIB was corrupt since I didn’t see anything in the stack trace that pointed to my code. After wasting several hours investigating that rat hole, I decided to try to do what the debugger didn’t help with and that’s track down the offending line. With breakpoints and Debugger(); calls (breakpoints don’t always work for me) I found that an IBOutlet was not being initialized and I was sending a message to nil. If the run-time was not going to flag this as an error, why would this cause a problem down the line? Arrggg!
Lesson learned, if a stack trace looks similar to the above, then look at your initialization code of your Nib objects.
At work, our software runs on Windows and Mac OS. I’m trying to reuse as much code as possible; not through some fancy cross-platform tools but by simply writing in portable C or C++ code and by using class wrappers that can each be implemented in the native platform. One thing I’ve been pretty pleased with XCode is it’s support of mixing Objective-C and C++ code fairly seamlessly.
Recently, in trying to port some C++ Windows code over I started having some memory crashes. Unfortunately the XCode debugger was of very little help with the stack trace not including any calls from my code. This was an excellent thread on some techniques to troubleshoot EXC_BAD_ACCESS problems. Fortunately, I didn’t have to try all the various techniques listed. After reading the entire thread I decided to pursue the notion that I might be over-releasing an object (though why should this be a problem? A warning perhaps but seems once a reference counter is down to 0 calling release again should be harmless). This DID lead me to the offending code so I was able to fix my problem without wasting too much time. Once again, the developer community saved me hours if not days of debugging. How did we get along as programmers before the Web?
Debugging AutoRelease problems
I haven’t had to "hook-up" help in a Cocoa appplication yet since the application I inherited at work already had it working. But recently, when the application invoked help I’ve been getting the message:
"Help isn’t available for <application name>"
I found this article to help me understand how help is hooked up in Cocoa.
I checked the required metatag and the info.plist values and they seemed in order. What worked for me is to remove the Help Book Folder from the resources folder and re-insert it. Be sure to select the radio button titled "Create Folder References for any added folders"
The one thing that is different in my Xcode 2.4.1 version project from the article was that the Resources folder exists inside a Frameworks folder.
This error message had me stumped for a while:
invalid conversion from ‘objc_object*’ to ‘int’
the line in question was something like this:
int iResult = [MyUtils utilsMemberFunc:param1,param2];
it doesn’t matter what the "to" type is, what is important is that you recognize that this message, in this context, is reporting that the utilsMemberFunc declaration was not found and due to objective-c’s dynamic binding it is assuming it returns an objc_object* rather than the type that utilsMemberFunc was declared to return. So why isn’t it finding the declaration? Because I used ‘,’ rather than ‘:’ to separate the parameters. Besides the fact my brain still thinks in C++, I use commas to separate parameters in a variable list alot ( [NSString stringWithFormat:@"%d,%d", num1, num2]).
Through trial and error and comparing similar code that works it finally dawned on me that my syntax was incorrect.
I'm running Xcode 2.4.1
I have an odd breakpoint problem that I have not seen written about. I can set breakpoints no problem, my program will break correctly. My problem is when I run my program again, though the breakpoints appear marked correctly in the UI and in the breakpoint window, none of the breakpoints break. Going to the command-line GDB (GNU debugger) via <Option><Apple> (must be in the debugger window) I type in "break info" and it reports no breakpoints!
Don't know what happened in my environment for this to start occuring but it is very inconvenient to re-enter all my breakpoints on each invocation. I hope I find the problem soon.
Update: I found the "Stop on Debugger()/DebugStr()" command in the Debug window. This will save me, for now, allowing me to break inside some initialization code which runs before I get a chance to set breakpoints. I just insert a Debugger(); call in the code where I want to "break".
Update: Today, Aug 26, 2008, "xcode breakpoint" is appearing at #1 in Google. In case you aren't reading the comments to this post, Aaron's suggestion:
In trying to access information from a quicktime file I came across my first pascal string (pstring). Trying to copy this string using strncpy or NSString:stringWithCString did not work so I looked at the memory and saw a number as the first byte. I recognized this as a pascal string so I searched on conversion from pstring to NSString and found this:
The documentation for CFString states: "in a method where you see an
NSString * parameter, you can pass in a
CFStringRef" but the compiler complained so as in the example code linked above, I resorted to using the NSString:stringWithFormat. My first thought was to simply use NSString:stringWithString.
Here is the wrapper function I came up with:
-(NSString*)NSStringFromPString:(unsigned char*) pstring
CFStringRef strRef = CFStringCreateWithPascalString (NULL, pstring, kCFStringEncodingMacRoman);
return [NSString stringWithFormat:@"%@",strRef];
Update 8/24/07: It seems the error when using stringWithString has something to do with what source is being compiled. If it is in an .mm file (enables C++ compatibility?) I get the error:
error: cannot convert ‘const __CFString*’ to ‘NSString*’ in argument passing
but if compiled in an .m file it works fine. It appears that in the former case, the compiler is being stricter, though a forced cast will eliminate the error message.
I’ve given the Development Documentation for XCode a few weeks, but yesterday, after spending half a day searching how to retrieve the Codec information from a quicktime file, I finally concluded that the best source of documentation is source code on the web. With the lack of examples the documentation is only of minimal help when you are new and trying to discover HOW to do things, not just reference information.
Two sites helpful in searching code are Krugle and Koder. Krugle has a nicer UI. I haven’t used Koder much.
Make sure you have implemented all members of your class. I had forgotten to implement my destructor