Here we have a piece of c code that goes into a dead loop, reading the current timestamp and resetting the random seed each time, after which it prints a random number and sleeps for one second. The seeds are consecutive, and Windows generates the first random number consecutively for consecutive seeds, which is not the case with Linux.
Many languages written in c that don’t have their own implementation of a random number generator also have this problem, e.g. lua 5.1
#include<time.h>
#include<stdlib.h>
#include<stdio.h>
#ifdef __linux__
#include <unistd.h>
#else
#include <windows.h>
#endif
void printRandoms(int lower, int upper,
int count)
{
int i;
for (i = 0; i < count; i++) {
int num = (rand() %
(upper - lower + 1)) + lower;
printf("%dn", num);
}
}
int main(){
while(1){
srand(time(NULL));
printRandoms(1,10000,1);
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
}
return 0;
}
The output:
On Windows:
I tried both gcc and clang.
1. gcc.exe (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders) 13.1.0
2. (built by Brecht Sanders) clang version 16.0.5
3. gcc.exe (MinGW-W64 x86_64-msvcrt-posix-seh, built by Brecht Sanders) 9.5.0
5237
5238
5239
5240
5241
5242
5243
5245
5246
5247
5248
On Linux:
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
5142
3660
7270
896
9500
3041
6659
5194
8809
7361
5960
I know that’s usually the wrong way to use srand(), but was just curious what led to the difference.
2
Answers
You seem to think
time( NULL )
is a strong seed, but it’s not. While the Linux version looks more random, it’s not. It’s just as predictable as the Windows version. That’s because it’s often possible to guess them time of seeding. And knowing that gives the stream of numbers, in both versions. (Even if you don’t know the exact time, you just have a few possibilities of streams.)srand
should be given a value as random as possible.The Windows version probably simply returns the seed as its first value. After all, you should have provided a random value to
srand
. To make it look just as unpredictable as the Linux version looks, simply callrand
after callingsrand
.Note that it doesn’t make sense to call
srand
more than once in a process.Note that
rand
should not be used anywhere where randomness is important (e.g. crpytography). Use a proper source of randomness for that.As C’s
rand(), srand(), RAND_MAX
are not specified to be very good for random number generation, some compilers choose a very weak implementation. I suspect it is in order to encourage better alternatives.MinGW-W64 x86_64 appears to be that way.