Jump to content
  • Advertisement
Sign in to follow this  
irreversible

How to lose friends and alienate coworkers.

This topic is 577 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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);
}
Edited by irreversible

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites

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... Edited by Nypyren

Share this post


Link to post
Share on other sites

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. Edited by Oberon_Command

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

 

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

Share this post


Link to post
Share on other sites

 

#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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!