Sunday, October 28, 2007

Don't Tread on My Data

"const" Means const

Method call parameter lists are contracts, plain and simple. They are meant to be held inviolate by the implementation of the method. To break that contract is to commit programming malfeasance. Here's something you should never, ever, ever do lest you earn a place across the River Styx condemned to debug memory leaks into infinity.

void ABadBadThing( const void* pData )
{
unsigned* pDataIn = (unsigned*) pData;

...

// Now go trample all over the callers data
*pDataIn = someUnsignedValue;

return;
}

Is it apparent what has happened? Classic "bait and switch." The implementer of this function has made a contract with me, the client, that if I call this method my data is "const" which means I can assume that it will be unchanged by the call. "const void* pData" means that what pData points to is immutable, it won't be changed; what goes in, comes back out.

The heinous sin was committed by the cast operation “unsigned* pDataIn = (unsigned*) pData" which in effect strips off the "const" attribution in the parameter list by creating a mutable alias to my data. The implementation of the method is now free to go take a big poop all over my data.

There are two parties to blame here. The first is the implementer that at some point was thoughtful enough to put a "const" on the parameter, then at some point decided to coerce the pointer into a mutable type. The second is the C++ programming language which allows users to abuse type casting.

Sometimes C++ makes me feel dirty and in dire need of a shower to cleanse myself. This is another one of those times. I found this little gem in library code I inherited for a project and it cost me about a day of debugging because I assumed my data would be unchanged when it came back.

Fool me once, shame on me.