阵列访问期间出现分段错误

Segmentation fault during array access

本文关键字:分段 错误 访问期间 阵列      更新时间:2023-10-16

我想从 [1,10] 中大量绘制 1 个整数,然后检查每个整数出现的次数。我写了这段代码,它正在编译但显示分段错误。你能指出问题出在哪里吗?

#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;
        }
}

如果你定义一个由 10 个元素组成的数组,就像你在这里所做的那样:

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

然后数组将具有索引 0-9。所以count的范围从count[0]count[9]不等。

但是,在这里:

count[rand]++;

rand为 10 时,您正在尝试访问不存在的count [10]

为了回答编辑中的后续问题,您需要循环并创建10000随机数,如下所示:

 for(int i=0;i<10000;++i)
 {
     int rand=di(dre);
当您在 10 个

不同的数字之间进行选择时,您会期望每个数字的计数约为 1000,并且分布均匀。

但是,当您打印结果时,将每个计数除以 10000:

count[foo]/=10000;

因此,这意味着现在每个计数很可能约为 0.1。当您将其存储在整数中时,它会向下舍入为零。

你调用count[rand]其中计数有 10 个项目,这意味着索引在 0..9 范围内,但 rand 在 1..10 范围内,所以每隔一段时间它就会调用count[10]这会导致你的 seg 错误。

使分布改为使用 [0..9]:std::uniform_int_distribution <int> di(0,9);

对于for (int foo: count)foo依次等于count中的每个元素。您需要在循环中单独使用 foo 而不是 count[foo] ,或者如果您需要索引,请使用显式for循环。

此外,std::uniform_int_distribution是包含边界的,因此您需要使用 0, 9 而不是1, 10来初始化它以索引到您的十元素count中。

您的均匀分布应定义为:

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

因为您的数组元素是从 0 索引到 9 的。按原样,您的rand变量最终将大于9此时您正在越界读取,从而导致未定义的行为。即使rand保持在边界内,基于范围的循环for也会显示UB,因为foo存在实际数组元素的值,但尚未用作索引。应改为通过引用传递:

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

此外,如果您使用的是 C++11,那么您将需要此处的 std::array 初始值设定项的双大括号:

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