Vincent Gable

September 27, 2008

CFShow is NSLog for Core Foundation Types

Filed under: MacOSX, Programming, Tips — Tags: , , , , — Vincent Gable @ 7:44 pm

CFShow(coreFoundationThingy) will print out a description of coreFoundationThingy to the console. Output looks something like:

{value = w:1186.000000 h:687.000000 type = kAXValueCGSizeType}

If NSLog() is printing something out as an NSCFType, try CFShow().

September 18, 2008

I Would Rather Have a Runtime Error Than a Compile Error

Filed under: Programming, Quotes, Reverse Engineering — Tags: , , , — Vincent Gable @ 6:49 pm

And the weird thing is, I realized early in my career that I would actually rather have a runtime error than a compile error. [(some laughs)] Because at that time… now this is way contrary to popular opinion. Everybody wants early error detection. Oh God, not a runtime error, right? But the debugger gives you this ability to start poking and prodding, especially in a more dynamic language, where you can start simulating things, you can back it up… You’ve got your time-machine debuggers like the OCaml one, that can actually save the states and back up.

You’ve got amazing tools at your disposal (in the debugger)… Whereas if the compiler gives you an error that says “expected expression angle-bracket”, you don’t have a “compiler-debugger” that you can shell into…

So, you know, in some sense, your runtime errors are actually kind of nicer.

– An excerpt from one of Steve Yegge’s (long!) talks.

I think there is a real nugget of truth in this. At runtime, you can examine your program’s state, but there is absolutely no way to do that at compile time. Without a debugger, you can’t just look at some nontrivial code and know what the value of x is when there’s an error reading y. (Adding "print x", recompiling, and trying again, would work of course, but that’s just using your compiler as an inefficient debugger!)

Similarly, Strong Typing vs. Strong Testing , essentially argues that some tests can only be made at runtime. (If you read any links on this page, read it, it’s much shorter and to the point).

September 16, 2008

-description, Little-Known Hero of Debugging

Filed under: Cocoa, MacOSX, Objective-C, Programming, Sample Code, Tips — Tags: , , , — Vincent Gable @ 7:50 pm

Or: How to Make NSLog() Useful With Your Objects

Say you have an archaically named NSArray that you want to inspect — it’s easy to do, since NSLog(@"The bestiary is %@", bestiary); prints out the array’s contents

2008-09-16 19:46:06.445 Tester[2678:10b] The bestiary is (
Cheetah,
Pumpa,
Jaguar,
Panther,
Tiger,
Leopard
)

But if you try to NSLog your own object, you get pretty useless output, like

myObject = <MyObject: 0×53f330>

Fortunately, it’s easy to fix! Just implement the method -(NSString*) description; and whatever it returns will be printed by NSLog and GDB (po object, will print object in GDB and the Xcode debugging console).

Here’s an (unfortunately complex) example,

- (NSString*) description;
{
  return [NSString stringWithFormat:@”<%@ %p> = {\n\tquestion=%@,\n\tanswer=%@,\n\tsource=%@\n}”, [self className], self, self.question, self.answer, self.source];
}

output:

myObject = <MyObject 0×53eed0> = {
  question=What is the Best Thing Ever Of All Times, Ever?,
  answer=The Internet!,
  source=http://www.cabel.name/2008/01/2007-cabel-yay-awards.html
}

Useful Formatters and such

These macros have made my debugging-life easer.

%p tells NSLog to print the address of a pointer.

-className returns gives the name of a class as an NSString.

Don’t manually print out a Cocoa struct, ever, there are already NSStringTo* functions to do that for you, like NSStringFromPoint().

NSStringFromSelector() works as advertized (and paired with NSSelectorFromString() is very useful in general).

%lld tells NSLog to print a long long (64-bit integer). See also, printf reference.

%Lf tells NSLog to print a long double. See also, printf reference.

Best Practices

Whenever you make a new object, I strongly recommended immediately implementing a description method, and religiously keeping it up to date (it’s not hard, honest!). This won’t fix bugs, but it will make finding some of them much easier.

August 5, 2008

Simplified Logging

Filed under: Cocoa, MacOSX, Objective-C, Programming, Sample Code, Tips, Usability — Tags: , , — Vincent Gable @ 11:44 pm

I have noticed a pattern in my Cocoa code, which I have been able to simplify. I often print out the value of a variable for debugging. 99 times out of 100, the code looks like this: NSLog(@"actionURL = %@", actionURL);, where actionURL is some variable.

But using the macros, I can say LOG_ID(actionURL);. This is shorter, and non-repetitive.

The macros I use to simplify debugging (2008-09-16):

#define FourCharCode2NSString(err) NSFileTypeForHFSTypeCode(err)

#define LOG_4CC(x) NSLog(@”%s = %@”, # x, FourCharCode2NSString(x))
#define LOG_FUNCTION() NSLog(@”%s”, __FUNCTION__)
#define LOG_ID(o) NSLog(@”%s = %@”, # o, o)
#define LOG_INT(i) NSLog(@”%s = %d”, # i, i)
#define LOG_INT64(ll) NSLog(@”%s = %lld”, # ll, ll)
#define LOG_FLOAT(f) NSLog(@”%s = %f”, # f, f)
#define LOG_LONG_FLOAT(f) NSLog(@”%s = %Lf”, # f, f)
#define LOG_OBJECT(o) LOG_ID(o)
#define LOG_POINT(p) NSLog(@”%s = %@”, # p, NSStringFromPoint(p))
#define LOG_RECT(r) NSLog(@”%s = %@”, # r, NSStringFromRect(r))
#define LOG_SIZE(s) NSLog(@”%s = %@”, # s, NSStringFromSize(s))

Look in assert.h for insight on how to roll your own debugging macros.

July 14, 2008

Crash Reporter Prefs

Filed under: MacOSX, Reverse Engineering, Tips — Tags: — Vincent Gable @ 8:48 am

/Developer/Applications/Utilities/CrashReporterPrefs.app can make crash reports much more useful.

Crash report-files are stored in ~/Library/Logs/CrashReporter/

Unfortunately, crash reports are not sent back to third-party developers, even when you send them to Apple.

July 7, 2008

Bug Triage Priorities

Filed under: Programming, Quotes — Tags: , — Vincent Gable @ 8:03 pm

Roughly, my triage order is:
* Data-loss bugs
* Unavoidable crashers
* Functionality-blocking bugs
* Avoidable crashers
* Avoidable bugs
* Misfeatures
* Performance issues
* Feature suggestions
* UI feedback
This is, of course, a rough ordering

-Wil Shipley

I totally agree that data-loss / corruption is a higher priority then crashes. You can upgrade|downgrade a crashy program. But once data is gone, it is gone. Protecting users data should be your prime directive. I have always strongly disagreed with any bug triage that put crashes at spot #1.

July 5, 2008

FourCharCode2NSString

Filed under: MacOSX, Objective-C, Programming, Sample Code, Usability — Tags: , , , — Vincent Gable @ 8:13 pm

As I have written before, the best way to convert a FourCharCode to an NSString* for NSLog()ing is to use the NSFileTypeForHFSTypeCode() function. But for the life of me I can’t remember that name, even though I use it about once a month. It’s too long, and it has too little to do with what I’m using it for.

So I have added the line:
#define FourCharCode2NSString(err) NSFileTypeForHFSTypeCode(err)
To my prefix-files, because I can remember FourCharCode2NSString().

UPDATE: (2008-08-06) There is an even easier way.

Powered by WordPress