我正在尝试为Eratosthenes的Sieve实现算法,但我不知道为什么这个程序崩溃了更大的程序。最初我使用的是vector
,但现在我正在使用动态内存分配来实现它。
#include<iostream>
#include<cmath>
#include<cstdlib>
using namespace std;
unsigned isqrt(unsigned value) {
return static_cast<unsigned>(sqrt(static_cast<float>(value)));
}
int main()
{
int t;
cin >> t;
long long * N;
long long * M;
long long n, m;
N = new long long[t];
M = new long long[t];
for(int i = 0; i < t ; i++){
cin >> M[i] >> N[i];
}
for(int i = 0; i < t ; i++){
n = N[i];
m = M[i];
bool * A;
A = new bool[n];
if(A == 0)
{
cout << "Memory cannot be allocated";
return 0;
}
for(int i=0;i < n;i++){
A[i]=true;
}
A[0] = false;
A[1] = false;
unsigned sqrt = isqrt(n);
for(int i = 2; i <= sqrt; i++)
{
if(A[i] == true){
for(int j = i*i; j <= n; j = j + i)
{
A[j] = false;
}
}
}
for(int i = m;i < n;i++)
{
if(A[i] == true )
cout << i << "\n";
}
delete[] A;
}
delete[] M;
delete[] N;
return 0;
}
程序因较大的n
和m
(~10 ^ 16)值而崩溃。请帮助我。
答案 0 :(得分:4)
for(int j = i*i; j <= n; j = j + i)
^^
如果j == n
,那么A[j] = false
将分配给超出数组末尾的元素。测试应为j < n
。
答案 1 :(得分:2)
如果你要用C ++编写一个Eratosthenes的筛子,那么如果你实际上使用 C ++,那就不要试着把它当作C和汇编语言之间的一些疯狂交叉。
#include <vector>
#include <iostream>
unsigned long primes = 0;
int main() {
int number = 10000000;
std::vector<bool> sieve(number,false);
sieve[0] = sieve[1] = true;
for(int i = 2; i<number; i++) {
if(!sieve[i]) {
++primes;
for (int temp = 2*i; temp<number; temp += i)
sieve[temp] = true;
}
}
std::cout << "found: " << primes << " Primes\n";
return 0;
}
答案 2 :(得分:1)
如果n足够大而导致内存分配错误程序将因此处错误的内存分配错误处理而崩溃
A = new bool[n];
if(A == 0)
{
cout << "Memory cannot be allocated";
return 0;
}
new不会在出错时返回0,但会抛出没有被捕获的std :: bad_alloc,这反过来会导致unexpected()然后终止()并最终调用abort() 。
正确的版本是:
try
{
A = new bool[n];
}
catch (std::bad_alloc& ba)
{
std::cerr << "Memory cannot be allocated: " << ba.what() << '\n';
}
答案 3 :(得分:-1)
在调试器中运行它以确定崩溃的位置并从那里进行调试。在那一点上很可能很明显。
您可以从IDE或命令行执行此操作。在后一种情况下,使用-g
进行编译并在gdb
等程序中运行。谷歌就像“gdb cheatsheet”一样开始使用。