【问题标题】:for loop is crashing on big numberfor 循环在大数字上崩溃
【发布时间】:2017-04-15 11:30:10
【问题描述】:

我有问题。我必须编写一个程序来计算随机生成的数字表的碰撞(碰撞测试)。例如表 [1,2,2,3,4,5,5,5,6] 有 3 次冲突。

我的问题是,每当我尝试将数字 n 增加到例如 int n = 5191401; 时,我的程序就会崩溃。怎么了?为什么它停止工作?我需要大量的随机数(比如 10^14)。

这是我的代码:

#include <iostream>
#include <gsl/gsl_rng.h>
#include <stdlib.h>
#include<cmath>

using namespace std;

int compare(const void * a, const void * b)
{
    return ( *(int*)a - *(int*)b );
}

int main (void)
{
    unsigned int seed=10540000;
    gsl_rng * r=gsl_rng_alloc (gsl_rng_minstd);
    gsl_rng_set(r,seed);
    gsl_rng_env_setup();
    int lPrzedzialow=400000000;
    int n = 519140;
    int z,lKolizji=0;
    int lwKomorkach[n-1];
    double dlPrzedzialu=1./(lPrzedzialow);

    for (int i = 0; i < n; i++)
    {
        lwKomorkach[i]=floor(gsl_rng_uniform (r)/dlPrzedzialu)+1;
    }

    qsort (lwKomorkach, n, sizeof(int), compare);

    for(z=0;z<=n-1;z++)
    {
        if(lwKomorkach[z+1]==lwKomorkach[z])
        {
            lKolizji++;
        }
    }

    cout<<endl<<lKolizji<<endl;
    gsl_rng_free (r);

    return 0;
}

【问题讨论】:

  • 10^14 比普通整数所能容纳的要大得多。你可能需要一个无符号的 __int64。在此处查看整数限制:msdn.microsoft.com/en-us/library/296az74e.aspx
  • n = 519150 远未接近整数限制,它对我不起作用;
  • @Sarah 停止这样做:int lwKomorkach[n-1]; 这不是标准的 C++。使用std::vector,如果您的问题消失,我不会感到惊讶。您正在使用非标准的“可变长度数组”,而且很可能您正在使用它们来破坏堆栈。使用标准 C++,std::vector。
  • @Sarah Please read this。它不仅详细解释了n 很大的问题,还详细说明了如何使用at() 解决您自己的边界条件问题。也退出使用qsort 并使用std::sort。
  • int n = 519140; int lwKomorkach[n]; --> 可能会导致stackoverflow....

标签: c++ loops for-loop random gsl


【解决方案1】:

您的问题有两个方面。

1) 您在声明数组时使用了非标准 C++ 语法。

2) 访问数组时,您很可能会越界。

解决第一个问题,这行代码不是标准的C++。

int lwKomorkach[n-1];

C++ 中的数组必须用编译时常量声明。此外,如果n-1 很大,则可能会超出保留的堆栈空间量。

缓解这种情况的方法是使用std::vector:

#include <vector>
//...
std::vector<int> lwKomorkach(n-1);

一旦你有了这个,为了确保你不会越界,你可以使用std::vector::at()函数来检查边界:

for (int i = 0; i < n; i++)
{
    lwKomorkach.at(i) = floor(gsl_rng_uniform (r)/dlPrzedzialu)+1;
}

如果i 超出范围,您将收到std::out_of_range 异常,而不是“崩溃”或更糟,不会发生崩溃并相信您的程序在实际运行不正常时正常运行。您应该在另一个 for 循环中应用相同的测试。

修复边界问题后,您可以将代码从 at() 更改为使用 [ ],因为边界错误已解决。

最后一个问题是qsort 的用法。请改用std::sort。 std::sort 更易于使用(无需到处进行强制转换),可以更容易地由编译器优化,并且可以用于任何类型(而qsort 仅适用于 POD 或 C 兼容类型)。

#include <algorithm>
//...
std::sort(lwKomorkach.begin(), lwKomorkach.end());

【讨论】:

  • 非常感谢!完美运行!
【解决方案2】:

就这样

int lwKomorkach[n-1];

for (int i = 0; i < n; i++)
{
    lwKomorkach[i]=floor(gsl_rng_uniform (r)/dlPrzedzialu)+1;

}

您正试图将 n 项放入 n-1 大小的数组中。我想它不会只是偶然地以低数量崩溃。

在第二个循环中它变得更糟

for(z=0;z<=n-1;z++)
{
    if(lwKomorkach[z+1]==lwKomorkach[z]){lKolizji++;}
}

当 z= n-1 时,您尝试分配给 lwKomorkach[n] 而 lwKomorkach 的最大索引可以是 n-2

【讨论】:

  • 您的代码中没有表格[3]。我说的是由 lwKomorkach[n-1] 定义的数组。
  • 它看起来如何更正?我尝试更改它,但没有任何效果
  • 好吧,将数组声明为 int lwKomorkach[n];并在第二个循环中,而不是 z
  • 我刚做了,现在即使是小数字也不起作用:
  • 如果您还没有这样做,请使用调试器查看您的错误。
猜你喜欢
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多