The following code snippet randomly shuffles an STL array of integers -- it works correctly on both Ubuntu and Red Hat. However, on my Mac OS X box, the array shuffles to the same order every time. The second section of the code prints the output of the random number generator, which is decidedly not random.
Am I doing something wrong, or did something change when I upgraded my OS X/XCode suite? Either way, is this a security hole? ... certainly a lot of legacy code that may have be used to generate random numbers could look like this, and suddenly be no longer random.
Thoughts?
The code (try it yourself):
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;
int main()
{
//First, let's initialize, shuffle, and print a random vector.
vector<int> myOrder;
for(int i = 0; i < 10; i++)
myOrder.push_back(i);
uint seed = time(NULL);
std::srand( seed );
std::random_shuffle(myOrder.begin(), myOrder.end());
for(vector<int>::iterator it = myOrder.begin(); it != myOrder.end(); it++)
cout << *it << "\t";
//Let's check the output of the PRNG:
cout << "\nMy seed is: " << seed << "\n==================\n";
for(int i = 0; i < 10; i++)
cout << rand() << "\t";
cout << endl;
}
Output from 3 runs on Ubuntu:
4 3 6 2 7 1 9 5 0 8
My seed is: 1395151370
==================
38394197 1995358147 65276563 2013488432 1137737660 1255414699 924908498 309981427 1799367638 1337198287
2 4 7 9 6 8 5 3 0 1
My seed is: 1395151371
==================
1281137856 2008486108 1477643146 1786210280 166055115 1227183121 819984618 1762177356 207844974 1730642206
3 6 0 5 7 8 1 4 2 9
My seed is: 1395151372
==================
397185149 960257000 1833707166 510257843 283547169 1218814437 1818880205 1086171377 1860201155 12516048
And now, output from 3 runs on OS X:
6 0 3 5 7 8 4 1 2 9
My seed is: 1395151529
==================
2085289957 535188259 1247555377 1780375578 1882685795 1276101667 521534680 1552603353 530759174 1969851427
6 0 3 5 7 8 4 1 2 9
My seed is: 1395151530
==================
2085306764 817663508 722721803 617835589 879311078 1746312939 622562224 862970584 1989537097 1829605489
6 0 3 5 7 8 4 1 2 9
My seed is: 1395151531
==================
2085323571 1100138757 197888229 1602779247 2023420008 69040564 723589768 173337815 1300831373 1689359551
template<class RandomIt> void random_shuffle(RandomIt first, RandomIt last);
// deprecated in C++14
uses an implementation-defined source of randomness that cannot be controlled.
Implementations often use std::rand, so calling std::srand to seed the prng could work but it's not portable.
You can use a random_shuffle that takes a third parameter:
C++11 (example from http://en.cppreference.com)
#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(v.begin(), v.end(), g);
copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
}
or
C++03
...
int my_random(int i) { return std::rand() % i;}
std::srand(seed);
std::random_shuffle(myOrder.begin(), myOrder.end(), my_random);
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With