2

I have a program containing multiple classes, some of which require random doubles and ints. In one of the classes, I defined a struct to seed the random engine and be able to generate random reals and ints through an object of that struct whenever I need one. The .hpp file with class and struct declations looks like this:

struct RNG {
public:
    static std::mt19937 gen;
    static std::uniform_int_distribution<uint32_t> dist_ui;
    static std::uniform_real_distribution<double> dist_d;
    uint32_t r_ui = dist_ui(gen);
    double r_d = dist_d(gen);
private:
    static unsigned seed;
};

class A {
private:
    uint32_t a_;
public:
    A();
};

The .cpp file looks like this:

#include "A.hpp"

unsigned RNG::seed = 42;
std::mt19937 RNG::gen(RNG::seed);
std::uniform_int_distribution<uint32_t> RNG::dist_ui(1, std::numeric_limits<uint32_t>::max());
std::uniform_real_distribution<double> RNG::dist_d(0.0,1.0);

A::A() {
    RNG* r;
    a_ = r->dist_ui(r->gen);
}

Now, if I call uniform_real_distribution with

r->dist_d(r->gen)

everthing works fine. However, if I call uniform_int_distribution with

r->dist_ui(r->gen)

as in the above snippet, I get a segmentation fault. The error also occurs if I define my struct only with int dist instead of both real and int, or if I change the boundaries of the int dist to [0,100) or whatever. Does anyone have a clue what happens here? I appreciate any help!

EDIT: I get the same error if I access the non-static members like this

RNG r;
a_ = r.r_ui;
Durd3nT
  • 163
  • 1
  • 7
  • 1
    `r` is unitialized, it doesn't point to anything useful - accessing it is Undefined Behaviour. – Yksisarvinen Nov 17 '19 at 21:34
  • 1
    @Yksisarvinen OP only accesses static members through it, so it should be fine. It threw me off at first too. – HolyBlackCat Nov 17 '19 at 21:34
  • 3
    @HolyBlackCat No, not "it should be fine". It has undefined behaviour. Period. If you want to access static members use `RNG::`. It's not the problem, though, per the edit. – Lightness Races in Orbit Nov 17 '19 at 21:43
  • Show your [mcve], including information _about_ the segmentation fault, not just that you get one. – Lightness Races in Orbit Nov 17 '19 at 21:45
  • @LightnessRaceswithMonica I remember reading something about dereferencing a null pointer not being undefined if you discard the result, but after looking it up again, I was probably wrong. – HolyBlackCat Nov 17 '19 at 21:52
  • @HolyBlackCat There are a lot of people who claim, without merit, that it's safe. Usually it's because they have a low-level interpretation of the term "dereference" and refuse to budge on it, despite knowing that C++ is an abstraction and despite understanding what UB means in the first place. – Lightness Races in Orbit Nov 17 '19 at 22:09
  • 1
    @Yksisarvinen [It's definitely been asked before.](https://stackoverflow.com/q/5248877/560648) – Lightness Races in Orbit Nov 17 '19 at 22:10
  • Thank you for your immediate help and @Yksisarvinen for your advice, I didn't think about this and corrected it. As to the problem; I managed to resolve it, but am still not sure what went wrong. When I constructed a minimal reproducible example for this post, all parts that I thought contained the error, suddenly worked fine. So I rebuilt my program step by step, and now everything works. While doing so, I also found a mistake where I was accessing elements of an std::vector outside its range. So this was probably related. – Durd3nT Nov 18 '19 at 12:02
  • PS: I added an edit to post making clear that I just messed up my code and there was (probably) no problem with . Sorry for wasting your time, I am rather new to C++ and not a very experienced programmer. And again, thanks a lot for your feedback! – Durd3nT Nov 18 '19 at 12:03

2 Answers2

5

I have a guess here. Is the object of type A also static/global? If so, maybe your problem is because the order of static initialization is not defined. So, you're accessing dist_ui before it's initialized.

Please post the rest of the code (the one that creates an instance of A) if it's not the case.

iliar
  • 932
  • 6
  • 11
0

A minimal reproducible example worked fine, in the end, I resolved the problem by carefully rebuilding my program. Doing so, I found wrong access of an std::vector, which was probably one of the reasons execution failed. So, long story short: I messed up my code and didn't look carefully enough before posting this question. However, as pointed out in the comments, I should not access uninitialized pointers as I am doing in my snippet below (RNG* r) even if they're static. Instead, use the scope resolution operator (::)

a_ = RNG::dist_ui(RNG::gen)
Durd3nT
  • 163
  • 1
  • 7