First of all, I'm working on multi-threaded code, which is always prone to strange behaviors and is very difficult to debug, but I wasn't really thinking that was of significance until I totally unwound the problem. There was unfortunately this delicate race condition which could make code which shouldn't work, suddenly work properly. Thus allowing me several hours of self indulgence as I mistakenly searched for the error in the compiler.
So I had a base class which needed to launch a thread and run its own handler:
class target { public: target() ; virtual ~ target() ; void launch() ; private: virtual void run(void) ; static void * entry(void *) ; } ; void target::launch() { pthread_t tmpthr ; pthread_create(& tmpthr, NULL, target::entry, this) ; } void * target::entry(void * atarget) { target * ref= (target *) atarget ; ref-> run() ; return ref ; }and then I had a sub-class which overrode the run() method.
class monitor_class : public target { public: monitor_class() ; protected: virtual void run(void) ; ... } ;Now in the debugger, monitor_class::run() would run, but from the command line target::run() would run instead (as demonstrated through the judicial placement of printf's--knowing how to debug without a debugger is a necessary skill, for there are many circumstances in which a debugger is not available or not helpful in assessing the problem.) So clearly, there was some bug in the compiler and I had to figure out what it was, or at least work around it for the time being.
First I took a look at the typecast in target::entry() but except for switching to dynamic_cast<target*>(atarget) which didn't work in the debugger either, that wasn't helping me. I then tried making target::run() a pure virtual (by defining it virtual void run() = 0, but that just got me an exception at runtime: "pure virtual being called". I then worked backward and did a test call to run() in target::launch(), before doing all the casting. This was also calling the wrong function, and after staring at this for a minute or two I thought to myself to look at where I was calling launch().
Turns out I had decided to be clever and called launch() here:
target::target() { launch() ; }
Ouch. Never call a virtual function from a constructor, you don't get the answer you want. At best you get the methods that belong to the constructor class, at worst the results is undefined. Of course launch() wasn't virtual when I put it there. I must have decided to get clever later and wasn't watching for this side effect (and somehow the debugger pandered to my bad habits and kept me happy right up until I tried to run it stand-alone). Well, I'm certainly not going to do that again.
Feb '04
Oops I dropped by satellite.
New Jets create excitement in the air.
The audience is not listening.
Mar '04
Neat chemicals you don't want to mess with.
The Lack of Practise Effect
Apr '04
Scramjets take to the air
Doing dangerous things in the fire.
The Real Way to get a job
May '04
Checking out cool tools (with the kids)
A master geek (Ink Tank flashback)
How to play with your kids