Thursday, August 23, 2007

Compiler Bug, or Not?

I'm a firmware engineer. We use C++ for our firmware. C++ has been disparaged by some great programmers, but they are also the ones who talk about how great Ruby and JavaScript are. Try writing real-time firmware with those! But I digress. Yesterday I had an interesting experience with a bug that took me far to long to find (the fix was easy). Let me see if I can explain this well enough to get some helpful feedback from the C++ geniuses that I know are lurking out there.

I added a new class to our firmware a couple days ago, and had it instantiated inside another class. The two classes can be simplified to look something like this:


class Bar
{
public:
    Bar();
    void initialize();
private:
    int x;
};

class Foo
{
public:
    Foo();
    void start();
private:
    Bar * bar;  
};

Not exactly like that, but close. Firmware isn't very complicated, right? So anyway, here are the implementations for each, roughly:


Foo::Foo()
{
    Bar * bar = new Bar();
}

void Foo::start()
{
    bar->initialize();
}

And for Bar:


void Bar::initialize()
{
    x = 5;
}

And, more or less, that's it. Some other class instantiates Foo and calls it's start method, and things blow up. Or, at least they should. Can anyone see why? You get the job if you can. OK, I'll tell you. It's the little re-declaration of the pointer, bar, inside the Foo constructor. It creates a new Bar, and stores the pointer to it in a variable local to the constructor. It goes out of scope and disappears when the constructor is done. Oops!

So then, when Foo::start() is called, the private member variable, bar, is uninitialized and what happens? Well, not quite what I would expect. You see, according to the crash dump and the debugger, it seemed to still have run the Bar::initialize() method! Apparently, and looking at the assembly code seemed to confirmed this, the function is found at compile time and the address of it is stuck right in the code. The pointer isn't used to find it at runtime at all. I never knew that.

Back to the crash. The crash happened because the hidden "this" pointer that was passed to the method had the wrong value. That's not a big surprise. Looking at the assembly code, "this" was used as an offset to calculate where to store that 5, also not a surprise. The 5 didn't end up inside the Bar class because the value of "this" was zero. Crash!

I was first led astray by the method call succeeding. If that had failed I would have immediately looked at the pointer, but since it worked, I assumed pointer == good. The other reason I had such a hard time catching this bug of mine was because our "debug" build worked! For some reason the compiler was still storing the pointer to the Bar instance inside Foo's private member variable. When Bar::initialize() was called it received the correct value for "this," and everything worked just like I intended. Guessing my intent is impressive and all, but not very useful if the optimized build doesn't include that feature too ;-). It took a few conversations with co-workers for me to realize what was going on and finally find the bug. At least we all learned something...

So my question for the panel: is what the debug build did a compiler bug on top of my code bug? Or am I just grasping for some dignity here, in light of my blunder? What about executing the Bar::initialize() method off of a bad pointer? Do other compilers do that?

Friday, August 17, 2007

Django Powered Sites

I guess I'm a little late finding out about this, but I'm excited I found my Django powered family website in the mosaic. C-11.

Saturday, August 11, 2007

F-Spot Hurts My Eyes

This is just a public complaint, because I'm too lazy to go file a bug report or something. I use F-Spot for managing my photos on my Ubuntu desktop. It's kind of cool and mostly does what I would expect it to. One thing that really bothers me though is how, when you are flipping through pictures, it shows each one blurry first, and then it come into focus. I suppose this is done for some kind of effect, because I've never seen any other photo software do this (gthumb and eog, to name a couple close competitors), but it drives me insane. I have bad eyes and have worn glasses since I was about 6 years old. Every time I flip to a new picture they strain to focus on it until it fully comes into focus on its own. If there is any way to make this stop, I'd love to hear about it.

And since I'm complaining about F-spot, I'll mention one other major beef I have with it (I've got a bad cold and am grumpy, forgive me). When you import photos, you choose a directory (or camera). When you make that choice it starts displaying all the photos in that directory and has a grayed out inactive button that says import. After a while it finishes and you can then highlight a subset of the photos in that directory and click on import. At this point, though, it has already imported every photo from that directory and your selection does nothing. The import button merely dismisses the import dialog. There seems to be no way to import only selected photos from a directory or camera. This is just dumb.

Phew. There. It feels good to get those off my chest. There a few other little complaints I have with f-spot, but overall, I really do like it.

Sunday, August 5, 2007

Too Many Gadgets

Packing for a family trip, we brought:

  • A cell phone, plus charger
  • A portable dvd player, plus charger
  • A digital camera, plus charger
  • An mp3 player, plus charger
  • A GPS, plus charger
  • A laptop, plus charger

As I plugged them all in to charge the night before, and then filled an entire backpack with them the next the morning, an iPhone started to look really attractive. I think when they get GPS on that thing it's going to be very hard to resist.