The Shape of Everything
A website mostly about Mac stuff, written by August "Gus" Mueller
» Acorn
» Retrobatch
» Mastodon
» Micro.blog
» Instagram
» Github
» Maybe Pizza?
» Archives
» Feed
» Micro feed
July 16, 2005
(This post is from my old, old, super old site. My views have changed over the years, hopefully my writing has improved, and there is now more than a handful of folks reading my site. Enjoy.)

Saturday, July 16th, 2005

I've made a new build of FlySketch, and I'm calling it 1.5b1. You can download it from this link if you would like to try it: FlySketch-1.5b1.dmg. Use at your own risk of course, but it's been very stable for me (now that I fixed a ridiculous undo bug).

I've also created a "latest" page like I do for VoodooPad. Here's the link. Whenever I run a scripted build of FlySketch it uploads it to the server and this page has a link to it. It's the latest and greatest version, with bugs just waiting to be discovered.

The documentation hasn't been updated yet, so no need to ding me about that- but if you do run into any bugs, I'd like to know about it.

...

(Geeky Mac OS programming things follow.)

Speaking of bugs, I fixed a big crasher in FlySketch the other day which had been bothering me for some time. It took a little while to narrow down to a reproducible case but it was pretty easy to fix once I found it. And since I like sharing little programming stories (and I just get dumb looks from my dogs when I tell the stories to them), I'll share this one with you.

It went something like this:

Lauch FlySketch. Draw, undo. Draw, undo. Crash.

Hrm. The crash log looked like this usually:

Thread 0 Crashed: 0 objc_msgSend_rtp + 32 1 -[NSInvocation setArgument:atIndex:] + 648 2 -[NSInvocation invokeWithTarget:] + 48 3 -[_NSUndoStack popAndInvoke] + 268 4 -[NSUndoManager undoNestedGroup] + 328 5 -[NSApplication sendAction:to:from:] + 108 6 -[NSMenu performActionForItemAtIndex:] + 392 7 -[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 104 8 -[NSMenu performKeyEquivalent:] + 272 9 -[NSApplication _handleKeyEquivalent:] + 220

Hrm... (Gus stares blankly into space, unable to come to any conclusions, and is slightly afraid that he's writing over some memory at startup or something which is only coming to light later on.)

I immediately headed over to Apple's Technical Note TN2124, otherwise known as "Mac OS X Debugging Magic". I tried a bunch of different things, and nothing helped. Well, crap.

Of course, this worked just fine at one point in the past... right? And I've got a subversion repository for some reason... right? So let's check out an old version of FS and see if that works. And then if it works, lets check out a newer version than that and see if that crashes. Repeat, etc.. until we find version x that works, and version x+1 that crashes. A bunch of svn co -r's and xcodebuild's later, and I find that the bug showed up between commits 406 and 407.

Cool, now I know I can narrow down and see specifically what I changed, by doing a "svn diff". Piece of cake... clickty click (Gus typing). Umph. 1800+ line changeset. Double crap. This is going to take a while.

Lesson #1- there's a reason why all the smart people who write books on version control say "make small changes and commit frequently". It's so you don't have to wade through 1800 lines to find the two or three that caused your bug.

After alot of digging and applying changes to version 406 that would later show up in version 407, I found the bug. It was in my base graphic class, in the dealloc method, and the change went from:

// v. 406 [fillColor autorelease]; fillColor = nil;

// v. 407 [self setFillColor:nil];

I was taking a little short cut that I had discovered a while back. Instead of touching my ivar directly, I would just use the accessor to release the memory it was holding on to. 1 line instead of 2. Less code = good.

Except for that whole undo bit that I completely forgot about in setFillColor:.

- (void)setFillColor:(NSColor *)aFillColor {

    if (fillColor != aFillColor) {
        [[[self undoManager] prepareWithInvocationTarget:self] setFillColor:fillColor];
        [fillColor autorelease];
        fillColor = [aFillColor retain];
        [self didChange];
    }
}

When I set a fill color, I naturally want the user to be able to undo it. Doing this in the accessor method is the standard place to do it, however by calling [self setFillColor:nil] in dealloc I was telling the undo manager to set it to the old version... on an object that isn't going to be around anymore in a few microseconds. So when undo is called, the undo manager says "your color shall now be red" on an object that isn't around anymore. NSUndoManager then proceeds to freak out and kills FlySketch in anger.

Lesson learned. And I'm sharing it so hopefully you won't make the same mistake I did.

That's it, story time is over. Go play with FlySketch 1.5 now, and bring me back some easy bugs to fix.

-- posted 1:14 pm