anotherone
anotherone

Reputation: 795

Segmentation fault during array access

I want to draw 1 integer from [1,10] a large number of times, then check how many times each integer appears. I wrote this code, it is compiling but showing segmentation fault. Can you, please, point out where the problem is?

#include <iostream>
#include <random>
#include <array>

int main(){
        std::random_device rd;
        std::mt19937 dre(rd());
        std::uniform_int_distribution <int> di(1,10);
        std::array<int,10> count{0};
        for(int i=0;i<10000;++i)
        {
                int rand=di(dre);
                count[rand]++;
        }
        for (int foo: count){
                count[foo]/=10000;
                std::cout << foo << " " << count[foo] << std::endl;
        }
}

Upvotes: 0

Views: 1851

Answers (4)

Steve
Steve

Reputation: 1757

If you define an array consisting of 10 elements, like you do here:

std::array<int,10> count{0};

Then the array will have indices 0-9. So count will range from count[0] to count[9].

However, here:

count[rand]++;

when rand is 10, you're trying to access count [10], which doesn't exist.

To answer the followup question in your edit, you're looping round and creating 10000 random numbers, here:

 for(int i=0;i<10000;++i)
 {
     int rand=di(dre);

And as you're picking between 10 different numbers, you'd expect the count of each one to be approximately 1000, with a uniform distribution.

However, when you come to print the results, you divide each count by 10000:

count[foo]/=10000;

So this means it's highly likely that each count is now approx 0.1. As you're storing it in an int, this gets rounded down to zero.

Upvotes: 4

Ron
Ron

Reputation: 15501

Your uniform distribution should be defined as:

std::uniform_int_distribution <int> di(0, 9);

because your array elements are indexed from 0 to 9. As-is your rand variable will eventually become greater than 9 at which point you are reading out of bounds thus causing undefined behavior. Even if rand stays within boundaries your range based for loop will exhibit UB because foo there is the value of the actual array element yet used as an index. Should be passed by reference instead:

for (int& foo : count) {
    foo /= 10000;
    std::cout << foo << '\n';
}

Also if you are using C++11 then you will need double braces for the std::array initializer here:

std::array<int, 10> count{ { 0 } };

Upvotes: 2

Quentin
Quentin

Reputation: 63124

With for (int foo: count), foo is equal to each element in count in turn. You need to use foo on its own in the loop instead of count[foo], or use an explicit for loop if you need the index.

Additionally, std::uniform_int_distribution is bounds-inclusive, so you need to initialize it with 0, 9 instead of 1, 10 to index into your ten-elements count.

Upvotes: 2

gonutz
gonutz

Reputation: 5582

You call count[rand] where count has 10 items, meaning indices in the range of 0..9 but rand is in the range of 1..10 so every once in a while it will call count[10] which causes your seg fault.

Make the distribution use [0..9] instead: std::uniform_int_distribution <int> di(0,9);

Upvotes: 2

Related Questions