WTF: Random Memory Contents

Monday September 3rdC++, Software Development, WTF Category

If any of you out there are able to give me ONE GOOD REASON why anyone would do something like this, then please let me know. Below are “customised” realloc() and malloc() I recently stumbled across (yes, they get called. A LOT):
[source:cpp]void *mcRealloc( void *P, int SIZE )
{
int oldSize = _msize( P );

P = realloc( P, SIZE );

if ( P )
{
for ( int i = oldSize; i < SIZE; i++ )
{
((char *) P)[i] = (char) rand();
}
}

return P;
}

void *mcMalloc( int SIZE )
{
void *P;

P = malloc( SIZE );

if ( P )
{
for ( int i = 0; i < SIZE; i++ )
{
((char *) P)[i] = (char) rand();
}
}

return P;
}[/source]Is it just me, or is this a huge WTF?

10 Comments

  1. Tom
    September 3, 2007

    You poor, poor man …

  2. IainB
    September 4, 2007

    I guess it’s designed to catch bugs to do with uninitialised memory, but that’s possibly the craziest way to do it I’ve ever seen.

  3. OJ
    September 4, 2007

    There’s absolutely no way that helps catch bugs revolving around uninitialised memory. There’s no boundaries added. There’s no “known value” set. There’s no tracking of which byte has which “rand” value. There’s no way of telling if the memory has actually been used or not after the call is returned. It’d be better to leave it alone!

    Bear in mind that the respective call to ‘mcFree’ is a direct mapping to the standard free() function.

    There is no point to this code.

  4. Vorlath
    September 8, 2007

    I’ve done this once (shame on me). But only because I couldn’t use a memory checker at the time. And only when I knew there was a bug in the code related to allocations but the program kept executing past it. By putting in random numbers, you make sure you’ll get an illegal access when your code incorrectly tries to use existing pointers in the newly allocated memory block. Without this, software that should normally crash can keep running when it incorrectly uses old data in newly allocated memory. This kind of debugging code isn’t supposed to survive though. But it does catch a certain class of bugs. Maybe the developer forgot to take it out? It would slow down the software drastically with that in place.

    Oh, why rand and not just zeros? So that you can tell what block of memory triggered what error. Rand will generate the same sequence of numbers on every run. So you can tell if it’s the same bug (or the x allocation) or not on different runs by looking at and writing down the value of the pointer that caused the program to crash (now that it does crash at the proper time). If you then try to fix something and you still get an error, then at least you can check if the pointer value is the same or not (whereas old and invalid pointers can all point to the same data structure and so does all the same value such as zero). It lets you know if you’ve actually changed anything toward that particular bug when you can’t track allocation (or other iteration) counts. The only time you’d ever do this is with really nasty pointer bugs and you can’t use a memory checker. It’s manual debugging basically. Like printf.

    As for production code reasons to use this, I cannot think of any. I have seen setting new allocations to some value to make sure the pages are in physical RAM. But rand would serve no purpose here. I can think of all sorts of crazy shit and I’ve got nothing. Well, maybe if you want to make sure that no old data on the system can get used by your software. Like having a bug that prints an invalid pointer where that memory location says “OJ shits up the wall!” entered by a user. Instead, it would print garbage (which is arguably better) and be sure that the NUL character would be encountered (mostly) within 256 characters instead of endlessly printing characters. Still, that’s pretty weak. It assumes your software has bugs or can be hacked. Then again…

  5. OJ
    September 9, 2007

    Thanks for the insightful comment Vorlath. I hadn’t really considered cases where memory checkers or other handy tools like that weren’t able to be used, and in that case I can see some value.

    Let me add to the confusion a bit more :) The random seed isn’t set to a constant. In fact, the only time it’s set is near the start of the application, and it’s set to time() (yup, the old ’srand(time(NULL))’ trick). So the seed is different each time the application runs. If debugging using rand(), surely you’d want to use a known/constant seed?

    I feel the same as you with regards to the production issue. If this code does indeed have some sort of value when debugging, it loses that value as soon as a release binary is built. There’s no excuse for having that in production code at all.

    We should also bear in mind that we’re using Visual Studio 2005 - with all the bells and whistles that come with it. Debugging memory issues is extremely easy, and this kind of code only hinders the process. It doesn’t really help it.

    I also think that having “OJ shits up the wall!” scattered throughout the system’s memory is a GOOD thing, not a bad thing ;)

    Cheers :)

  6. Vorlath
    September 10, 2007

    HAHA! I would probably end up agreeing with you on that last point. And if you’re using VC with a random seed, then I’m at a complete loss as well. No clue why someone would randomize allocated blocks.

    I’m still with IainB. This was debugging time code only to catch bugs with unitialised memory forcing the program to crash so that the dubugger can catch it. No way this could be used in production code. Definitely WTF?!

  7. Vault-Co
    September 17, 2007

    This was common during the former era of embedded systems programming around the 1960’s. It was a way to do mem compares to see if memory had been initialized correctly. It has not been common practice for around 30 years or more.

  8. OJ
    September 28, 2007

    I have found out the reason (if you can call it that) for this code. The original author told me:

    I put that in to “simulate” debug in release mode, and forgot to take it out.

    Riiiiiiiight.

  9. Mark
    October 10, 2007

    [no preview, no html escaping. blast!]

    Yeah that’s totally insane!

    I, of course, would have used:

    int i = oldSize;
    int j = ((i+3)>>2)<<2;
    while (i > 24;
    }
    while (i < SIZE-3 )
    {
    (int *)&((char *)P)[i] = rand();
    i+=4;
    }
    while (i > 24;
    }

    which is clearly superior, being 32-bit aligned and calling rand() around 1/4 as many times.

    Of course a REALLY smart programmer would cache the result of the first call of rand() and use memset().

    Join me again next week for another episode of COMPLETELY MISSING THE POINT :)

  10. OJ
    October 11, 2007

    LOL! Nice one :)

Leave a comment

Size

Colors