How to lose friends and alienate coworkers.

Started by
12 comments, last by matt77hias 7 years, 1 month ago

This thread is semi-fictitious, because I don't have coworkers in my coding life. Nevertheless, I was trying to think of insidious ways to plant latent bombs in some otherwise cherished shared code (or your own, should you so desire!). Here are a few to get the ball rolling. Please feel free to post your own nefarious ideas!

The first two exploit the potentially single most abusive concept in coding I have in recent memory. To top things off, neither of these particular examples triggers a compiler warning in VS.

Do this: change your GetWidth() and/or GetHeight() functions to return uints overnight. Then get popcorn and wait for someone to do something like this:


set_screencoord(x - (GetWidth() >> 1), y - (GetHeight >> 1));

For context - I recently changed my window extent getters to uint32s. Suffice to say I'm seriously considering changing them back.

Or here's one of my favorites. Can go undetected for weeks, this one.


for(size_t i = 0; i < counter; ++i) { if(condition) { vec.quick_erase(vec.begin() + i); i--; } }

This one has gotten me a few times. The dirty bugger.

And finally something a little bit more evil. Something far more insidious, should you be naive enough to rely on simple behavior. I discovered this one in my memory manager the other day (although mine had nothing to do with clearing memory or anything that could be corruptive in any way, but rather had to do with reporting errors that led me to believe I had a serious cross-thread memory leak on my hands (which I didn't); that being said, I'd like to stress that the use of ZeroMemory() in this case is as illustrative as it gets!). Also, in my case I was dealing with smart pointers and a multithreaded memory manager, which obfuscated the issue quite a bit (although this has no real bearing on the problem at hand). What I'm trying to say is that don't judge the code - I've stripped the example down to something really really dumb and basic for reasons of clarity.

This one can be tough, but can you figure it out without further hints? The only assumption you should make is that allocations can be tightly packed, in that baseAddr2 = (baseAddr1 + size1 + sizeof(size_t)).

EDIT: a few more assumptions for the sake of clarity: assume that no (unintentional or otherwise) mistake or malicious manipulation of the allocated pointer has been made prior to calling mydelete(). Also assume that the compiler has not rearranged the members of allocrec_t - this is not the issue. Don't assume anything other than perfectly valid use of C++ in all its glory.


struct allocrec_t
{
   void* baseAddr;
   size_t size;
};
void mydelete(void * ptr)
{
   allocrec_t* ar = (allocrec_t*)ptr;

   ZeroMemory(ar->baseAddr, ar->size);
}
Advertisement

Remind me to never get on your bad side!

How about adding a

#define TRUE FALSE
hidden deep in a header file somewhere?
Definition of a man-year: 730 people trying to finish the project before lunch
One way I shot myself in the foot and wasted days debugging was this:

#if defined(TESTING)
#   define protected public
#   define private public
#endif
Some libraries in the project were compiled with and without TESTING defined. Works on gcc for some reason but causes seemingly random runtime errors on Windows.
"I would try to find halo source code by bungie best fps engine ever created, u see why call of duty loses speed due to its detail." -- GettingNifty

This one has gotten me a few times. The dirty bugger.

struct allocrec_t
{
   void* baseAddr;
   size_t size;
};
void mydelete(void * ptr)
{
   allocrec_t* ar = (allocrec_t*)ptr;

   ZeroMemory(ar->baseAddr, ar->size);
}


OK, you win. I humble myself before you and admit my inadequacy as a programmer. You are the master and I am but a lowly hobbyist. :(

Now that the groveling is done.... What is wrong here? What am I missing? I've been banging my head against a wall for weeks!

This one has gotten me a few times. The dirty bugger.

struct allocrec_t
{
   void* baseAddr;
   size_t size;
};
void mydelete(void * ptr)
{
   allocrec_t* ar = (allocrec_t*)ptr;

   ZeroMemory(ar->baseAddr, ar->size);
}


OK, you win. I humble myself before you and admit my inadequacy as a programmer. You are the master and I am but a lowly hobbyist. :(

Now that the groveling is done.... What is wrong here? What am I missing? I've been banging my head against a wall for weeks!


Not actually invoking free (depends on what that function is SUPPOSED to do, though. if it's pooling then that might be acceptable), not sanity checking ar->size (it could be uninitialized), passing void* instead of allocrec_t* bypassing any hope of type checking helping you not f*** up calls to it with the wrong type, etc, etc...

This one has gotten me a few times. The dirty bugger.

struct allocrec_t
{
   void* baseAddr;
   size_t size;
};
void mydelete(void * ptr)
{
   allocrec_t* ar = (allocrec_t*)ptr;

   ZeroMemory(ar->baseAddr, ar->size);
}


1. Unless I'm missing something, shouldn't that be something like (allocrect_t*)((unsigned char *)ptr - sizeof(allocrect_t))?
2. With the code as written, if ptr == baseAddr (which I assume it is, which is why I ask the above question) the ZeroMemory will make ar->size be 0, so if the records are tightly packed the record will show as having a 0 size - so the ACTUAL record size will be lost on deallocation, which can cause all kinds of bugs.

Not actually invoking free (depends on what that function is SUPPOSED to do, though. if it's pooling then that might be acceptable), not sanity checking ar->size (it could be uninitialized), passing void* instead of allocrec_t* bypassing any hope of type checking helping you not f*** up calls to it with the wrong type, etc, etc...


giphy.gif

#if defined(TESTING) # define protected public # define private public #endif

And this is why we need a reflection API in C++^^

🧙

#if defined(TESTING) # define protected public # define private public #endif

And this is why we need a reflection API in C++^^

Nope. There are many good reasons for (static!) reflection in C++, but this sure as hell isn't one of them. private parts of a class are NOT part of the API. protected parts are only part of the API for things that derive from it. So you should never, ever, do this.

This topic is closed to new replies.

Advertisement