C++ 在C+中实现Eratosthenes筛选时,内存错误低于预期限值+;
我的问题与所描述的一个问题有关。我已经写了一个C++实现的ErasoStes筛选器,如果设置目标值太高,它会导致内存溢出。正如在那个问题中所建议的,我可以通过使用布尔C++ 在C+中实现Eratosthenes筛选时,内存错误低于预期限值+;,c++,visual-studio,out-of-memory,C++,Visual Studio,Out Of Memory,我的问题与所描述的一个问题有关。我已经写了一个C++实现的ErasoStes筛选器,如果设置目标值太高,它会导致内存溢出。正如在那个问题中所建议的,我可以通过使用布尔而不是普通数组来解决这个问题 但是,我遇到的内存溢出值比预期值低得多,大约n=1200 000。在上面的线程中的讨论表明,正常的C++布尔数组使用每个条目的字节,因此,对于2 GB的RAM,我期望能够以“代码> n=2×000×000×000 /代码>的顺序到达某个地方。strong>为什么实际内存限制要小得多? 为什么使用(将布尔
而不是普通数组来解决这个问题
但是,我遇到的内存溢出值比预期值低得多,大约n=1200 000
。在上面的线程中的讨论表明,正常的C++布尔数组使用每个条目的字节,因此,对于2 GB的RAM,我期望能够以“代码> n=2×000×000×000 /代码>的顺序到达某个地方。strong>为什么实际内存限制要小得多?
为什么使用
(将布尔值编码为位而不是字节)会使可计算限制增加八倍以上
下面是我的代码的一个工作示例,n
设置为一个小值
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
int main() {
// Count and sum of primes below target
const int target = 100000;
// Code I want to use:
bool is_idx_prime[target];
for (unsigned int i = 0; i < target; i++) {
// initialize by assuming prime
is_idx_prime[i] = true;
}
// But doesn't work for target larger than ~1200000
// Have to use this instead
// vector <bool> is_idx_prime(target, true);
for (unsigned int i = 2; i < sqrt(target); i++) {
// All multiples of i * i are nonprime
// If i itself is nonprime, no need to check
if (is_idx_prime[i]) {
for (int j = i; i * j < target; j++) {
is_idx_prime[i * j] = 0;
}
}
}
// 0 and 1 are nonprime by definition
is_idx_prime[0] = 0; is_idx_prime[1] = 0;
unsigned long long int total = 0;
unsigned int count = 0;
for (int i = 0; i < target; i++) {
// cout << "\n" << i << ": " << is_idx_prime[i];
if (is_idx_prime[i]) {
total += i;
count++;
}
}
cout << "\nCount: " << count;
cout << "\nTotal: " << total;
return 0;
}
或者,更改n=1200 000
C:\Users\[...].exe (process 3144) exited with code -1073741571.
Press any key to close this window . . .
我正在Windows上使用默认设置的Microsoft Visual Studio解释器。将注释转换为完整答案:
您的操作系统在内存中保留一个特殊的部分来表示程序的调用堆栈。每个函数调用都会将新的堆栈帧推送到堆栈上。如果函数返回,堆栈帧将从堆栈中移除。堆栈框架包括函数参数和函数局部变量的内存。剩余的内存称为堆。在堆上,可以进行任意内存分配,而堆栈的结构由程序的控制流控制。堆栈已满时(例如,由于嵌套函数调用过多或由于本地对象过大),会为堆栈保留有限的内存,从而导致堆栈溢出。因此,应该在堆上分配大型对象
堆栈/堆上的常规引用:
在C++中堆堆上分配内存,可以:
- 使用
向量是_idx_素数(目标)代码>,它在内部执行堆分配,并在向量超出范围时为您释放内存。这是最方便的方式
- 使用智能指针管理分配:
auto is_idx_prime=std::make_unique(目标)代码>当数组超出作用域时,这也会自动释放内存
- 手动分配内存。我提到这一点只是为了教育目的。正如Paul在评论中提到的,通常不建议手动分配内存,因为您必须再次手动释放内存。如果您有一个具有许多内存分配的大型程序,那么不可避免地会忘记释放一些分配,从而造成内存泄漏。当你有一个长时间运行的程序,比如一个系统服务,重复的内存泄漏最终会填满整个内存(从个人经验来看,这在实践中绝对会发生)。但从理论上讲,如果你想手动分配内存,你可以使用
bool*is_idx_prime=newbool[target]
然后使用delete[]is\u idx\u prime
再次解除分配
数组在堆栈上分配,而向量在堆上分配。堆栈的大小比堆的大小更有限。要在堆上分配数组,可以使用bool*is_idx_prime=new bool[target]
然后稍后delete[]是\u idx\u prime代码>。或者,auto是_idx_prime=std::make_unique(目标)代码>,如果您想要自动释放(这是一个好主意)。如果您想要增加堆栈大小:@f9c69e9781fa194211448473495534请不要首先建议new[]
和delete[]
。这是最后的手段。我使用的是Microsoft Visual Studio解释器——不,它是编译器,不是解释器。然后是:for(unsigned int i=2;i
——每次循环迭代时,您都在计算sqrt
。只需计算一次,并存储该值——然后使用该值。
C:\Users\[...].exe (process 3144) exited with code -1073741571.
Press any key to close this window . . .