【发布时间】:2020-10-23 20:35:57
【问题描述】:
我的问题与here 描述的问题有关。如果我将目标值设置得太高,我已经编写了一个 Eratosthenes 筛子的 C++ 实现,它会导致内存溢出。正如该问题中所建议的,我可以通过使用布尔值 <vector> 而不是普通数组来解决问题。
但是,我在n = 1 200 000 附近遇到了比预期低得多的内存溢出值。上面链接的线程中的讨论表明,普通的 C++ 布尔数组为每个条目使用一个字节,因此使用 2 GB 的 RAM,我希望能够到达 n = 2 000 000 000 的某个位置。 为什么实际内存限制如此要小得多?
为什么使用<vector>(将布尔值编码为位而不是字节)会使可计算限制超过八倍?
这是我的代码的一个工作示例,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;
}
输出
Count: 9592
Total: 454396537
C:\Users\[...].exe (process 1004) exited with code 0.
Press any key to close this window . . .
或者,更改 n = 1 200 000 会产生
C:\Users\[...].exe (process 3144) exited with code -1073741571.
Press any key to close this window . . .
我在 Windows 上使用默认设置的 Microsoft Visual Studio 解释器。
【问题讨论】:
-
你的数组是在栈上分配的,而向量是在堆上分配的。堆栈的大小比堆更受限制。要在堆上分配一个数组,你可以使用
bool *is_idx_prime = new bool[target];,然后是delete[] is_idx_prime;。或者,auto is_idx_prime = std::make_unique<bool[]>(target);,如果您想要自动解除分配(这是个好主意)。 -
如果要增加堆栈大小:stackoverflow.com/q/40157847/3684343
-
@f9c69e9781fa194211448473495534 请不要先建议
new[]和delete[]。这是最后的手段。 -
我正在使用 Microsoft Visual Studio 解释器 -- 不,它是编译器,而不是解释器。然后是:
for (unsigned int i = 2; i < sqrt(target); i++) {——每次循环迭代时,您都在计算sqrt。只需计算一次,然后存储该值 - 然后使用该值。
标签: c++ visual-studio out-of-memory