[C++] Curious problem with rand()

Started by
10 comments, last by King Mir 10 years, 6 months ago

This isn't a problem per se as I have solved it, but it intrigues me.

Basically rand() isn't generating the same sequence of numbers for the same seed. My program is very long and split into over 40 classes so it wouldn't make sense to post everything here, but check this: after 2 days of playing around with different parts of my code I ended up replacing every call to rand() and srand() to custom versions, and now everything works fine. Now I run my program 10 times with the same seed and it always generates identical output, but that is not the case with the stdlib version.

I tried to reproduce this by writing a small program that outputs rand() results to files but it works as expected so I'm guessing either the C/C++ runtime or one of the third-party libraries I'm using is calling rand() behind the scenes at some point. Is that possible or is all this just a coincidence somehow?

I'm using the following software:

  • Compiler: MinGW 4.7.2
  • Libraries: SDL 2.0.0 along with SDL_Image and the png/zlib libraries it comes with

Thanks in advance if anyone knows.

Advertisement

so I'm guessing either the C/C++ runtime or one of the third-party libraries I'm using is calling rand() behind the scenes at some point. Is that possible or is all this just a coincidence somehow?

Either your own code has another srand/rand hidden in it somewhere that you've missed, or a bit of 3rd party code does.
That sounds like the only logical explanation.

This is why globals/singletons are bad dry.png

so I'm guessing either the C/C++ runtime or one of the third-party libraries I'm using is calling rand() behind the scenes at some point. Is that possible or is all this just a coincidence somehow?

Either your own code has another srand/rand hidden in it somewhere that you've missed, or a bit of 3rd party code does.
That sounds like the only logical explanation.

This is why globals/singletons are bad dry.png

I thought so. I don't want to blame SDL of messing with the state of rand() but I don't see how my code could be doing it, if it runs fine with my custom version. ;-;


I thought so. I don't want to blame SDL of messing with the state of rand() but I don't see how my code could be doing it, if it runs fine with my custom version. ;-;

You should be able to step into a rand() call a bit to find the memory address of the seed and place a data breakpoint on it.

You should use the new C++11 random header instead of rand; it solves this problem, and gives you better guarantees about uniform results.

Often, If you use static initialization on a global level, you can't tell which order the objects are created in.

Usage of rand() here may cause code invoking rand() in a different order than expected.

Of course, if the same build is causing different sequences, that's a different thing ohmy.png.

(Also, i must agree with Mir, stl http://www.cplusplus.com/reference/random/ is really sweet - I use it a lot.)

so I'm guessing either the C/C++ runtime or one of the third-party libraries I'm using is calling rand() behind the scenes at some point. Is that possible or is all this just a coincidence somehow?

Either your own code has another srand/rand hidden in it somewhere that you've missed, or a bit of 3rd party code does.
That sounds like the only logical explanation.

This is why globals/singletons are bad dry.png

Hehe, agreed.

You should use the new C++11 random header instead of rand; it solves this problem, and gives you better guarantees about uniform results.

I've looked into that. It's a but too hardcore for my current needs.

Often, If you use static initialization on a global level, you can't tell which order the objects are created in.

Usage of rand() here may cause code invoking rand() in a different order than expected.

Of course, if the same build is causing different sequences, that's a different thing ohmy.png.

(Also, i must agree with Mir, stl http://www.cplusplus.com/reference/random/ is really sweet - I use it a lot.)

What do you mean by "static initialization on a global level"? Like initializing global variables outside of a function? I avoid doing that. :P

What do you think the random seed is if not a global variable initialised outside a function (and modified by calling rand(), or srand()).

You already found 1 solution (roll your own replacement or better make a class that encapsulates a specific seed so you can use a separate random generator per class instance).

and uniform_real_distribution and uniform_int_distribution probably aren't as scary as they probably look... (example here http://www.cplusplus.com/reference/random/uniform_int_distribution/ )

The names are a tad verbose though ;)

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

and uniform_real_distribution and uniform_int_distribution probably aren't as scary as they probably look... (example here http://www.cplusplus.com/reference/random/uniform_int_distribution/ )

The names are a tad verbose though ;)

Aliases/typedefs to the rescue! wink.png


using random_gen = std::uninform_int_distribution;

Are you sure your own code isn't calling rand() somewhere inbetween two calls? Generally, I assume my own code is the problem rather than the standard library - though it's possible that there is some bug, the majority of the time, I eventually find out my own code is the source of the bug.

Do a Ctrl+F for rand() and srand(), and see where else your own code might be interfering. Any call to rand() or srand() elsewhere in your code will mess up the sequence - this is one of the problems the new random generators solve (you can have separate generators for each purpose that requires it).

If you think SDL 2.0 calls it (SDL 1.6 didn't, afaik), you could do a Ctrl+F for 'rand' in SDL's source code.

Dropping frames due to frame rate and calling rand() in dropped frames is a culprit too.

Class solution is the best, don't let your logic, frame rate independent calls interfere with rand called for graphics. And so on. Some random numbers are more crucial than others (e.g. smoke effects, can look a bit different, random decisions of enemies wants to stay the same otherwise cascading lack of random sync effects start happening. This is the butterfly effect for computer programs).

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

This topic is closed to new replies.

Advertisement