MultiLevelMenu

Feb 26, 2013

Explicit Overrides

In the last two days, I have been twice bitten by the loose nature of legacy C++ language.

I had developed a base class that abstracts the core features of a module a year back. The class itself was a great success. Since developing it for a specific module, I successfully refactored another module to use this and was able to do so in a relatively short window of 1 week. This is the background.

Recently, I had an opportunity to re-use this class for another module and having been successful earlier twice, I guess I was a little callous in using it without referring to the accompanied documentation. The design requires that I override a bunch of methods and admittedly I was as little cocky -- if I had designed and implemented it earlier, it should be a snap for me to re-use it. So I wrote the code, compiled it, removed a few syntax errors and dropped it into test. All good, except that couple of overridden methods were not being invoked!

WTF? It also so happened that the callback to the overridden methods were triggered by an external event. Off I went tracing this path to see what's going on. Nothing wrong there either. WTF??

With nowhere else left to investigate, I went back to the base class design. And it was then that I realized the rather embarrassing mistake that I had made. I guess the code is perhaps worth a thousand words -- so here it goes.

Base class implementation:
class Base {
protected:
   virtual void onInitialize();
   virtual void onShutdown(bool fGraceful);
};
And here's the derived class:
class Derived : public Base {
protected:
   virtual void onInitialize();
   virtual void onShutdown();
};
Note the mistake? I had forgotten about the bool fGraceful parameter to onShutdown() and as a result it was defined as a new method in the derived class!

This is precisely the kind of problem that explicit overrides feature in C++11 allows you to evade. If you have a conforming compiler (I didn't), you can declare the derived class as
class Derived : public Base {
protected:
   virtual void onInitialize() override;
   virtual void onShutdown() override;
};
What the trailing override does is to inform the compiler that onShutown() is a method that is overridden from its namesake in the base class. And the compiler, seeing that the prototype for the method in derived class doesn't match what's in the base, would raise an error which would allow you to spot the problem and fix it, even when you're overconfident and cocky!

As for me, I don't have the luxury of using a C++11 compiler and have to live with the possibility that I will make these mistakes again!

Feb 6, 2013

Back to the roots

For the past couple of weeks, I have been working on something that I thought I had left behind a long time ago, a very long time ago -- a windows device driver!

I had launched my career writing drivers, first for OS/2 and then eventually for Windows. When I say Windows, I'm referring to Windows NT 3.51. That's correct, NT 3.51! And here's a surprise, the first Windows NT driver that I worked on ran on PowerPC platform! IBM was readying their new state-of-the-art PC platform and to play it safe wanted to give the user the choice of platforms to run -- OS/2 and Windows NT.

Being a new platform, the toolsets were not quite as well developed as they were for the more contemporary and stable x86. WinDBG (a far cry from the WinDBG of these days) had issues syncing the source line information in the PDB with the actual source files. Quite often I had to resort to using the disassembly to isolate the root cause and fix it. Another challenge that I faced then was that the x86 driver had plenty of inline assembly which had to be ported to either C or PowerPC's RISC instruction set.

But what sets apart the driver development experience then and now is the advances made with the virtualization technology. Gone are the days of NULL modem cable and the rather long wait with every WinDBG command. Instead you work with multiple VMs with a virtual serial port mapped to a named pipe and debugging different versions of the driver simultaneously! The fact that VM states can be saved and cloned at will really makes driver development a breeze.

One thing however, has not changed much. Much of NT driver is still written C with very little C++. It's a shame that MS has not managed to update their compiler such that it can generate a driver safe PE image. Let's hope that this will change in the near future.

Anyway, it's hard not to feel like I'm going back to my roots.