c++ 数组大小以及如何管理大数组?
Posted
技术标签:
【中文标题】c++ 数组大小以及如何管理大数组?【英文标题】:c++ array size and how to manage large array? 【发布时间】: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? 【参考方案1】:您遇到了整数溢出问题。
您分配j = i*i
。当i
等于99999
时,i*i
是9999800001
,这很可能高于您平台上的INT_MAX
。在 32 位平台上,INT_MAX
为2147483647
,低于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)
【讨论】:
我下次自己解决问题,谢谢!以上是关于c++ 数组大小以及如何管理大数组?的主要内容,如果未能解决你的问题,请参考以下文章