Search code examples
c++randomuuid

Side-effect of std::srand/rand and libuuid uuid_generate


For testing I need reproducible random numbers. The randomness isn't that important. Currently I'm setting a seed std::srand(x) and use std::rand() to generate. As expected the numbers are always the same on multiple runs with the same seed.

For some other parts I need UUIDs. I use the utils-linux libuuuid.

But running this code:

  std::srand(2);

  uuid_t uuid;
  
  int x = std::rand();
  uuid_generate(uuid);
  int y = std::rand();

y is different on every run.

I already tried to use uuid_generate_time,uuid_generate_time_safe but this doesn't generate fully random UUIDs on multiple calls:

d4e25820-92ca-11eb-9b39-f91e898522ad
d4e25821-92ca-11eb-9b39-f91e898522ad
d4e25822-92ca-11eb-9b39-f91e898522ad
d4e25823-92ca-11eb-9b39-f91e898522ad

Is there any other way I could implement this?


Solution

  • As expected the numbers are always the same on multiple runs with the same seed.

    Until they are not. rand() is not required to use a certain algorithm. It can change if you upgrade - or if you compile on a different platform.

    It may also be affected by other functions as you've noticed.

    You could use a generator from <random> instead. Every instance of such a generator will be totally unaffected by other functions that you call.

    #include <uuid/uuid.h>
    
    #include <iostream>
    #include <random> // std::mt19937, std::uniform_int_distribution
    
    auto& prng() {
        // Create a static seeded PRNG to use everywhere in the program
        // thread_local std::mt19937 instance(std::random_device{}());
    
        // A PRNG with hardcoded seed for testing:
        thread_local std::mt19937 instance(2);
        return instance;
    }
    
    int main() {
        uuid_t uuid;
        std::uniform_int_distribution<int> dist(0, 10000);
    
        int x = dist(prng());
        uuid_generate(uuid);
        int y = dist(prng());
        std::cout << x << '\n' << y << '\n'; // 4360 and 1851 - everywhere
    }