Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中实现Eratosthenes筛选时,内存错误低于预期限值+;_C++_Visual Studio_Out Of Memory - Fatal编程技术网

C++ 在C+中实现Eratosthenes筛选时,内存错误低于预期限值+;

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>为什么实际内存限制要小得多? 为什么使用(将布尔

我的问题与所描述的一个问题有关。我已经写了一个C++实现的ErasoStes筛选器,如果设置目标值太高,它会导致内存溢出。正如在那个问题中所建议的,我可以通过使用布尔
而不是普通数组来解决这个问题

但是,我遇到的内存溢出值比预期值低得多,大约
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 . . .