我尝试使用筛选方法查找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.I得到结果4203,因此从1到40000有4203个素数
我知道32位操作系统中数组的最大字节数是0x7fffffff字节。
100000个字符或40000个字符远小于0x7fffffff字节。
为什么当数组大小为100000时,程序为carsh。当数组大小为40000时,该程序有效吗?我的代码有什么问题吗?
答案 0 :(得分:4)
您有整数溢出问题。
您指定j = i*i
。当i
等于99999
时,i*i
为9999800001
,这很可能高于您平台上的INT_MAX
。在32位平台上,INT_MAX
为2147483647
,低于9999800001
。
这里有两行用于比较:
2147483647
9999800001
由于整数溢出,您的程序有不确定的行为。
答案 1 :(得分:2)
问题在于这一行:
for(int j=i*i; j<100000; j += i)
i*i
超出界限,j溢出并变为负数,使得这一行:
a[j] = '0';
段错误
答案 2 :(得分:1)
为什么你需要使用数组呢?您可以考虑使用更简单的算法,例如:
<input id="file1" type="file" value="" style="background-color: red;opacity:0;filter:alpha(opacity=0);cursor: pointer; padding-top:3px;width:25px;" name="file">
该算法输出9592作为从0到100000的素数。
答案 3 :(得分:1)
关于溢出的所有其他答案都是正确的。
回答一个潜在的后续问题:我怎么能首先避免/发现这个问题?好吧,一些编译器可以为未定义的行为提供运行时检测。
以下是我使用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)