Had a really bad day with C++. Two strange bugs ruined it for me.
The first one had to do with the use of the ternary operator without proper parenthesis around it, while working with the shift operator on streams:
ostringstream ostr;
ostr << "bla bla" << x?y:z;
// This becomes
(ostr << "bla bla" << x) ? y : z;
// Which was simply becoming
ostr << "bla bla" << x;
A stupid bug like this inside a distributed app caused me to spend several hours. The bug was manifesting itself in a barrier operation, where different sets of distributed processes that were supposed to barrier independently, were barriering all at once, and the resulting incorrect counter was causing a deadlock!
Once I fixed the bug, another one followed. This time operator overloading and function overloading together were causing trouble:
void foo(X x) {}
template<class Y>
void foo(Y y) {}
And there is a class Z that implements an evil cast operator to class X.
In this setup foo(z) resolves to foo<Z>(z) but the coder has intended to call foo((X)z). The code used to work before the templated overload was added.
This was causing a rather strange segfault in a distributed app, and for some reason not showing up in standalone mode. After some more hours, this bug got cleared as well.
Given that I also spent a good deal of debugging and refactoring time yesterday with the evil problem of static object construction order (which is best eliminated via lazy initialization), as well as destruction order, I started to have some questions about C++. Not that I don't know all these problems. I do know them very well. But when there is so much depth and complexity in the application logic (multiple threads, database connections, forked processes, incremental checkpointing, cross-process synchronization, etc), having to deal with the warts of C++ becomes really annoying.
However, despite all its shortcomings, there is something about C++ that still attracts me. It is somewhat like enjoying the smell of your own armpit.
No comments:
Post a Comment