I might write a tip every week: I certainly seem to make enough mistakes to come up with them with such frequency.
Today I quickly point out a possible bug that can easily come about in C++ if you're altering interfaces. I had an stdlib vector of items that was being passed in from another class by reference that was then passed to a function:
When I came to making my code more efficient, I noticed that the internals of f() would be better suited to work with an array of doubles, rather than an stdlib vector. (To be precise I was passing vertex data to OpenGL for rendering, but I've greatly simplified the story for this post.)
Taking advantage of the contiguous storage afforded by stdlib vectors I simply passed a pointer to the first element, thus bypassing the auxiliary members of std::vector and effectively providing a simple array reference:
So far so good.
Eventually I altered the structure of DataSource (and this is why interfaces should be frozen before implementation, people!) to always pass around pointers where necessary, to help avoid accidental data duplication. I figured that my compiler would help me update all my references to
items so I didn't spend too much time tracking down all affected lines.
The result was this:
My expectations fell apart the moment I realised that relying wholly on compiler error messages is a Bad Idea. In fact, the above code is not an error; it merely isn't what I meant. Instead of giving me a pointer to the first element in the vector, it gave me the address of the pointer to the vector, which wasn't entirely useful. This side effect of C++'s implicit array-access-to-pointers had me chasing a segmentation fault in OpenGL for three days.
The corrected code reads thus:
And that could probably be done a whole lot nicer; but it compiles, runs and functions without mangling my machine's memory.
The moral of today's story is that if you really, really must alter an interface during or even after implementation, do not rely on your compiler to help you find change points: search for them yourself with a fine tooth comb. Or, ideally, just get your interface right the first time. That's what I'll be doing from now on.
Updated 11/08/2010: Left-aligned asterisks/ampersands in types, and replaced "STL" with "stdlib". I've learned a few things in two years.