This little story is about why reinventing the wheel is not only wasteful but could also be dangerous.
On one sunny day I inserted some pretty innocent
std::map into a
added a couple of one-liners, made sure it does what’s supposed to, committed
and pushed. In some minutes I hear a scream. The damn thing crashes on a
Linux. Why? It’s dead simple, it surely worked for me, there just cannot be
anything wrong with it, it must work. Right?
It just didn’t. After a quick look it was pretty clear – it’s a GCC bug. Perhaps the version is too recent and it has to be crawling with bugs. I started trying other versions but the problem wouldn’t go away. Well, it’s pretty clear now – it’s a GCC family bug! That would be a glorious discovery.
We sit down together and start to minimize the example, trying to reproduce it with fewer lines of code. We are trying this and that, replacing types with simpler ones, making all kinds of changes, renaming classes, moving them to different files, rearranging the lines, etc., etc. Other people come and join us, we are three, four, five and people keep coming. Everyone’s interested, everyone’s got a theory.
There are wild versions of how the
mutable keyword or a
crash the whole thing without even being called. How one should not be using
STL for anything since it’s a piece of crap and has never been stable. How C++
is a rotten language and nothing even remotely close to reliable or at least
deterministic could be produced with it. Many, many ridiculous theories, just
because any normal ones don’t make sense.
The time goes by. It’s already the second day. It’s going to be the third
soon. A bunch of people are involved. The air is electrified. We are already
down to just a few lines of code. It appears that the destructor of
is causing all the trouble. But it’s used everywhere else and everything has
been ok so far. In this case though the map is part of the structure that is
inserted into a homegrown version of
std::vector that is used everywhere else
and has been ok so far as well.
We start to get suspicious but nobody yet dives into blasphemy and tries to
CVector (let’s call it that way). After all it underpins the whole
foundation, it’s used everywhere and has been for years. It’s definitely
better and more reliable than
std::vector; it’s faster and smarter
and it’s written by the cool guys (though, not exactly compatible and
sometimes needs duct tape and a bit of voodoo to work). But the line is
crossed and we start to poke around the
CVector code. And…
There it was. One big shiny
memmove in the
resize function. It
seems the person who wrote that class thought there was nothing dangerous in
moving some memory from one place to another. We used to do that in C all the
time. It’s just a bunch of dumb bytes after all. But C++ is no C and moving an
object to another place without telling it (read assigning or
copy-constructing) could break it. This what apparently was happening with
std::map shipped with GCC.
The problem was fixed in a minute by replacing
One minute fix which took a few people many hours to identify and track down.
All of which could be avoided in the first place if someone didn’t try to
reinvent the wheel driven by the not invented here syndrome.