C++ std::未进入交换空间的错误分配
我试图理解为什么当我似乎有足够的(虚拟的?)内存可用时,我会出现std::bad_alloc异常。 本质上,我有一个素数生成器(Eratosthenes筛(尚未分段)),其中我为一个指示符数组生成布尔值,然后为我在命令行上指定的边界下找到的素数生成整数 我有1GB的RAM(其中一些会被我的操作系统(Ubuntu10.04)占用,可能其中一些无法用作堆内存(我错了吗?)和2.8GB的交换空间(我相信在安装Ubuntu10.04时会自动设置) 如果我将上限设置为600000000,那么我要求为我的指示符数组提供0.6GB的内存,为我的素数数组提供大约30000000*4字节的内存(稍微高估了一下,因为有26355867个素数小于500000000),以及一些变量;这意味着我需要大约.72(+可以忽略不计)GB的内存,我认为这应该由可用的交换空间来覆盖(我知道触摸这些东西会让我的程序慢得可笑)。然而,我得到了性病::坏的 有人能指出我这里遗漏了什么吗?(在粘贴上一个错误之前,最后一件将长整型改为整型的事情是seg错误(虽然我的数字远低于2^31,但我看不出溢出的地方)-仍在努力找出这个错误) 我的代码如下所示(在不影响我自己对更快算法等的研究的情况下,我会很感激这里的任何代码改进!(即,如果我犯了重大错误) main.cppC++ std::未进入交换空间的错误分配,c++,heap,C++,Heap,我试图理解为什么当我似乎有足够的(虚拟的?)内存可用时,我会出现std::bad_alloc异常。 本质上,我有一个素数生成器(Eratosthenes筛(尚未分段)),其中我为一个指示符数组生成布尔值,然后为我在命令行上指定的边界下找到的素数生成整数 我有1GB的RAM(其中一些会被我的操作系统(Ubuntu10.04)占用,可能其中一些无法用作堆内存(我错了吗?)和2.8GB的交换空间(我相信在安装Ubuntu10.04时会自动设置) 如果我将上限设置为600000000,那么我要求为我的指
#include <iostream>
#include <cmath>
#include "Prime.hpp"
#include <ctime>
#include <stdio.h>
#include <cstring>
//USAGE: execute program with the nth prime you want and an upper bound for finding primes --too high may cause bad alloc
int main(int argc, const char *argv[])
{
int a = strlen(argv[1]);
clock_t start = clock();
if(argc != 2)
{
std::cout << "USAGE: Enter a positive inputNumber <= 500000000.\n"
<< "This inputNumber is an upper bound for the primes that can be found\n";
return -1;
}
const char* primeBound = argv[1];
int inputNum = 0;
for(int i = 0; i < strlen(argv[1]); i++)
{
if(primeBound[i] < 48 || primeBound[i] > 57 || primeBound[0] == 48)
{
std::cout << "USAGE: Enter a positive inputNumber <= 500000000.\n"
<< "This inputNumber is an upper bound for the primes that can be found\n";
return -1;
}
inputNum = (int)(primeBound[i]-48) + (10 * inputNum);
}
if(inputNum > 600000000)//getting close to the memory limit for this machine (1GB - memory used by the OS):
//(each bool takes 1 byte and I'd be asking for more than 500 million of these
//and I'd also asking for over 100000000 bytes to store the primes > 0.6 GB)
{
std::cout << "USAGE: Enter a positive inputNumber <= 500000000.\n"
<< "This inputNumber is an upper bound for the primes that can be found\n";
return -1;
}
Prime p(inputNum);
std::cout << "the largest prime less than " << inputNum << " is: " << p.getPrime(p.getNoOfPrimes()) << "\n";
std::cout << "Number of primes: " << p.getNoOfPrimes() << "\n";
std::cout << ((double)clock() - start) / CLOCKS_PER_SEC << "\n";
return 0;
}
#包括
#包括
#包括“Prime.hpp”
#包括
#包括
#包括
//用法:使用所需的第n个素数和查找素数的上限执行程序——过高可能导致错误的alloc
int main(int argc,const char*argv[]
{
int a=strlen(argv[1]);
时钟启动=时钟();
如果(argc!=2)
{
std::cout程序内部可使用的内存量受到以下两个较小值的限制:1)可用虚拟内存,2)可用地址空间
如果在具有平面内存模型的平台上将程序编译为32位可执行文件,则单个进程的可寻址空间的绝对限制为4GB。在这种情况下,可用交换空间的大小完全无关。在平面内存32位程序中,即使仍然有4GB,也不能分配超过4GB的空间大量的可用交换空间。此外,这些4GB可用地址中的很大一部分将保留用于系统需要
在这样一个32位的平台上,分配大量的交换空间是有意义的,因为它可以让您同时运行多个进程。但它无法克服每个特定进程的4GB地址空间障碍
基本上,可以将其视为一个电话号码可用性问题:如果某个地区使用7位数的电话号码,那么一旦该地区可用的7位数电话号码用完,为该地区生产更多的电话就不再有任何意义——它们将不可用。通过增加交换空间,你基本上可以“生产电话”。但您已经没有可用的“电话号码”
当然,在平面内存模式的64位平台上也存在同样的问题。但是,64位平台的地址空间非常大,不再是瓶颈(你知道,“64位应该对每个人都足够了”:)由于程序的内存使用非常容易分析,只需完全固定内存布局。不要动态分配任何内容。使用std::bitset
获得固定大小的位向量,并将其作为全局变量
std::bitset< 600000000 > indicators; // 75 MB
std::位集<600000000>指示符;//75 MB
这不会占用磁盘空间。操作系统只会在您沿着阵列前进的过程中分配零页。它可以更好地利用每一位
当然,一半的位表示偶数,尽管只有一个偶数素数。是一对素数生成器,可以优化这些东西
顺便说一句,如果可能的话,最好避免显式地编写new
,避免从构造函数调用函数,并重新调用std::bad_alloc
,以避免将对象构造成无效状态。分配筛选时
void Prime::allocateIndicatorArray(int num)
{
try
{
primeIndicators = new bool[num];
}
catch(std::bad_alloc ba)
{
std::cout << "not enough memory :[";
}
lastStorageSize = num;
}
尝试分配int
数组中的lastStorageSize
元素
如果num
约为5亿,则您所需的空间约为2GB。根据操作系统/过度使用策略,这很容易导致分配错误,即使您实际上只需要一小部分空间
筛选完成后,将noOfPrimes
设置为找到的素数的计数-使用该数字分配素数数组。第一个问题是“正在运行哪些其他进程?”
2.87 GB的交换空间在所有运行
过程;它不是每一个过程。坦率地说,在现代
系统,2.8GB对我来说相当低。我不会尝试运行
最新版本的Windows或Linux,内存小于2GB,并且
4GB交换(Linux的最新版本,至少在Ubuntu中是如此)
尤其是发行版,似乎启动了很多守护进程
你可能想试试top
,在上面排序
虚拟内存大小,只看其他进程有多少
拿着
cat/proc/meminfo
也会给你带来很多有价值的信息
关于实际使用内容的信息。(在我的系统上,
使用bash
,再加上Firefox
,只运行两个xterm
,我
在8GB的系统上,只有3623776KB的可用空间
使用的内存可能是磁盘缓存之类的东西,
如果应用程序请求,系统可以缩小该范围
内存。)
第二,关于seg故障:默认情况下,Linux不会
始终报告allwa
std::bitset< 600000000 > indicators; // 75 MB
void Prime::allocateIndicatorArray(int num)
{
try
{
primeIndicators = new bool[num];
}
catch(std::bad_alloc ba)
{
std::cout << "not enough memory :[";
}
lastStorageSize = num;
}
void Prime::allocatePrimesArray()
{
try
{
primes = new int[lastStorageSize];
}
catch(std::bad_alloc ba)
{
std::cout << "not enough memory :[";
}
}