【问题标题】:c++ array size and how to manage large array?c++ 数组大小以及如何管理大数组?
【发布时间】:2016-03-17 03:57:28
【问题描述】:

我尝试使用筛法找出从 1 到 100000 有多少个素数。 这是我的代码:

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    char *a = new char[100000];
    memset(a, '1', 100000*sizeof(char));

    for(int i=2; i<100000; i++)
    {
         if(a[i] == '1')
         {
              for(int j=i*i; j<100000; j += i)
              {
                   a[j] = '0';
              }
         }
    }

    int count = 0;
    for(int i=2; i<100000; i++)
    {
         if(a[i] == '1')
              count++;
    }
    cout << count << endl;

    delete [] a;
    return 0;
}

这段代码编译没有错误,但是当我运行它时,程序崩溃了。

我将数组大小从 100000 更改为 40000。我得到结果 4203,所以从 1 到 40000 有 4203 个素数

我知道我的 32 位操作系统中数组的最大字节是 0x7fffffff 字节。

100000 个字符或 40000 个字符都远小于 0x7fffffff 字节。

为什么当数组大小为100000时,程序carsh。当数组大小为40000时,程序工作?我的代码有什么问题吗?

【问题讨论】:

  • 既然是C++,为什么不是std::vector?

标签: c++ arrays memory-management


【解决方案1】:

您遇到了整数溢出问题。

您分配j = i*i。当i 等于99999 时,i*i9999800001,这很可能高于您平台上的INT_MAX。在 32 位平台上,INT_MAX2147483647,低于9999800001

这里它们分为两行进行比较:

2147483647
9999800001

由于整数溢出,您的程序具有未定义的行为。

【讨论】:

    【解决方案2】:

    问题出在这一行:

    for(int j=i*i; j<100000; j += i)
    

    i*i 超出范围,j 溢出并变为负数,使这一行:

    a[j] = '0';
    

    段错误

    【讨论】:

      【解决方案3】:

      为什么需要使用数组?您可以考虑使用更简单的算法,例如:

      #include  <iostream>
      using  namespace  std;
      
          int  main()
          {
            int  N;
            int count = 0;
            cin >> N;
            for (int i = 2; N > 0; ++i)
            {
              bool  isPrime = true;
              for (int j = 2; j < i; ++j)
              {
                if (i  % j == 0)
                {
                  isPrime = false;
                  break;
                }
              }
              if (isPrime)
              {
                if (i > N)
                  break;
                count++;
                cout << i << "\n";
              }
            }
            cout << "The number of primes from 0 to " << N << " is " << count << endl;
      
            char stop;
            cin >> stop;
            return  0;
          }
      

      此算法输出 9592 作为从 0 到 100000 的素数。

      【讨论】:

        【解决方案4】:

        关于溢出的所有其他答案都是正确的。

        回答一个潜在的后续问题:我如何首先避免/检测到这种情况?嗯,一些编译器可以为未定义的行为提供运行时检测。

        这是我在使用 UBSan (what is UBSan?) 运行您的代码时得到的结果:

        $ clang++ -fsanitize=undefined  overflow.cpp 
        $ ./a.out 
        overflow.cpp:14:26: runtime error: signed integer overflow: 46349 * 46349 cannot be represented in type 'int'
        Segmentation fault (core dumped)
        

        作为参考,第 14 行是这一行:

                  for(int j=i*i; j<100000; j += i)
        

        【讨论】:

        • 我下次自己解决问题,谢谢!
        猜你喜欢
        • 2011-08-05
        • 1970-01-01
        • 1970-01-01
        • 2014-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多