Error in STL Random Generator program

May 27, 2019 at 9:33am
I'm trying out the random generation facilities of STL.
The following code produces a histogram for a normal distribution for 30 rows over 200 tries.

It works, and the output seems to be correct, but the program ends with the following error:

"munmap_chunk(): invalid pointer

RUN FINISHED; Aborted; core dumped; real time: 130ms; user: 0ms; system: 0ms"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  #include <random>
#include <iostream>

using namespace std;

class Rand_int {
public:
    Rand_int(int low, int high): dist{low, high}{}
    int operator()(){return dist(re);}
private:
    default_random_engine re;
    normal_distribution<> dist;
};

/*
 * 
 */
int main(int argc, char** argv) {
    Rand_int rnd{0, 29};
    
    vector<int> histogram(30);
    for (int i = 0; i < 2000; ++i) {
        ++histogram[rnd()];
    }
    
    for (int i = 0; i < histogram.size(); ++i) {
        cout << i << "\t";
        for (int j = 0; j < histogram[i]; ++j)
            cout << '*';
        cout << endl;
    }
    return 0;
}


g++ --version:
"g++ (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0"

compile arguments:
"-g -std=c++14"

Using NetBeans 11.0

Why do I get such an error?

Thank you for your help!

Edit: Running the code on cpp.sh with "Standard Input option" set to "None" gives the same error, while setting it to "Interactive" works fine without any errors.
Last edited on May 27, 2019 at 9:39am
May 27, 2019 at 9:51am
A normal distribution is not restricted within some finite limits. The first argument to the std::normal_distribution constructor is the mean, and the second argument is the standard deviation.
May 27, 2019 at 10:25am
Ahh, thank you! I think I understand the problem now.

I was using std::normal_distribution constructor like std::uniform_int_distribution with a high and a low value but that's not how standard deviation works.

I was writing outside of my vector<int> and that was the cause of the error.

I've corrected my code, both the standard_distribution constructor and my for loop to make sure I'm not accessing invalid elements.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <random>
#include <iostream>

using namespace std;

class Rand_int {
public:
    Rand_int(double low, double high): dist{low, high}{}
    int operator()(){return dist(re);}
private:
    default_random_engine re;
    normal_distribution<> dist;
};

/*
 * 
 */
int main(int argc, char** argv) {
    Rand_int rnd{15, 5};
    
    vector<int> histogram(30);
    for (int i = 0; i < 2000; ++i) {
        int d{rnd()};
        if (d < histogram.size())
            ++histogram[d];
    }
    
    for (int i = 0; i < histogram.size(); ++i) {
        cout << i << "\t";
        for (int j = 0; j < histogram[i]; ++j)
            cout << '*';
        cout << endl;
    }
    return 0;
}


Please, let me know if I've missed anything or there are other important things that I need to look after.

Thanks!
May 27, 2019 at 10:46am
This code "works" but I just want to point out two things.

1. The std::normal_distribution can give you negative values. Your condition (d < histogram.size()) only happens to reject negative values because histogram.size() returns an unsigned integer type which forces d to be converted to an unsigned integer type (which turns negative values into large positive values) before the comparison takes place.

2. The std::normal_distribution returns floating-point values which you convert to integers by just throwing away the decimal part. This means that all values in the range (-1, 1) will map to 0 which makes 0 about twice as likely as it should be. For your current parameters it isn't easily noticeable but if you change line 19 to something like Rand_int rnd{5, 5}; you'll see a spike at 0 that shouldn't be there.
Last edited on May 27, 2019 at 10:49am
May 27, 2019 at 10:56am
Thank you so much!
Topic archived. No new replies allowed.