Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rand() broken on OS X Mavericks/XCode 5.1? (or, "is this a massive security hole, or am I just a bad programmer??") [duplicate]

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  
like image 475
user3433072 Avatar asked Dec 31 '25 12:12

user3433072


1 Answers

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);
...
like image 196
manlio Avatar answered Jan 03 '26 00:01

manlio



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!