-
Casting type safety to the wind
2008-03-06 16:11 in /tech/HallOfShame
I spent most of yesterday hunting down a segfault in one of our unit tests. Here is a greatly simplified version of the code: can you see the bug?
#include <string> void bar(size_t* len) { *len = 0; } int main(void) { std::string buf; int len = 255; bar((size_t *)&len); return 0; }
Here’s a hint: maybe it doesn’t segfault for you.
Hint #2: the segfault is in basic_string::~basic_string().
Well, the title sort of gives it away. The bug is the cast. On 64-bit RHEL, ints are 4 bytes while size_t is 8 bytes. When bar() is called, it not only sets len to 0, but also overwrites an internal member variable of the string. Roughly speaking, this results in a null pointer exception, although it’s little more subtle than that because of some tricky details of the implementation of basic_string.
What makes this extra fun is that depending on the precise platform you are on and your compiler flags, this code might run just fine. For example, optimization might inline bar() and move len into a register, which side-steps the problem.
The moral, I suppose, is don’t cast when you could just use the right type to start with; don’t use C-style casts; and if you are stuck with C, be very, very careful about casting pointer types. Which, of course, you all already knew. Except whoever wrote that code.
Leave a comment
Please use plain text only. No HTML tags are allowed.