我使用三维char数组实现了一个bloom过滤器(位表),它运行良好,直到达到无法再分配内存并提供 bad_alloc 消息的程度。在分配600MB后,它在下一个扩展请求中给出了这个错误。
布隆过滤器(阵列)预计会增长到8到10GB。
这是我用来分配(扩展)位表的代码。
unsigned char ***bit_table_=0;
unsigned int ROWS_old=5;
unsigned int EXPND_SIZE=5;
void expand_bit_table()
{
FILE *temp;
temp=fopen("chunk_temp","w+b");
//copy old content
for(int i=0;i<ROWS_old;++i)
for(int j=0;j<ROWS;++j)
fwrite(bit_table_[i][j],COLUMNS,1,temp);
fclose(temp);
//delete old table
chunk_delete_bit_table();
//create expanded bit table ==> add EXP_SIZE more rows
bit_table_=new unsigned char**[ROWS_old+EXPND_SIZE];
for(int i=0;i<ROWS_old+EXPND_SIZE;++i)
{
bit_table_[i]=new unsigned char*[ROWS];
for(int k=0;k<ROWS;++k)
bit_table_[i][k]=new unsigned char[COLUMNS];
}
//copy back old content
temp=fopen("chunk_temp","r+b");
for(int i=0;i<ROWS_old;++i)
{
fread(bit_table_[i],COLUMNS*ROWS,1,temp);
}
fclose(temp);
//set remaining content of bit_table_to 0
for(int i=ROWS_old;i<ROWS_old+EXPND_SIZE;++i)
for(int j=0;j<ROWS;++j)
for(int k=0;k<COLUMNS;++k)
bit_table_[i][j][k]=0;
ROWS_old+=EXPND_SIZE;
}
数组的最大允许大小是多少,如果这不是问题,我该怎么办呢。
编辑: 它是使用32位平台开发的。
它运行在64位平台(服务器)上,内存为8GB。
答案 0 :(得分:5)
32位程序必须从虚拟内存地址空间分配内存。其中存储了大量代码和数据,内存是从它们之间的漏洞中分配的。是的,你可以希望的最大值是大约650兆字节,这是最大的可用漏洞。从那里开始迅速下降。您可以通过使数据结构更加智能化来解决它,例如树或列表而不是一个巨大的数组。
您可以使用SysInternals的VMMap实用程序更深入地了解流程的虚拟内存映射。您可能能够更改DLL的基址,使其不会在地址空间的空区域中间垂直。然而,你将获得超过650 MB的可能性很小。
在64位操作系统上有更多的喘息空间,32位进程具有4 GB的地址空间,因为操作系统组件以64位模式运行。您必须使用/ LARGEADDRESSAWARE链接器选项才能允许进程使用它。尽管如此,这只适用于64位操作系统,您的程序仍然可能在32位操作系统上爆炸。当你真的需要那么多虚拟机时,最简单的方法就是将64位操作系统作为先决条件,并构建针对x64的程序。
答案 1 :(得分:1)
32位进程可以访问的最大内存数据理论上是4GB(实际上它会稍微小一些)。因此,您不能同时在内存中拥有10GB数据(即使操作系统支持更多)。此外,即使您动态分配内存,可用的免费存储也会受到堆栈大小的限制。
进程可用的实际内存取决于生成可执行文件的编译器设置。
如果确实需要那么多,请考虑在文件系统中保留(部分)数据。
答案 2 :(得分:1)
32位机器为您提供4GB的地址空间。
操作系统保留了部分内容(默认情况下在Windows上有一半,给你自己2GB。我不确定Linux,但我相信它保留1GB)
这意味着您的流程有2-3 GB。
在这个领域,需要考虑几个方面:
以及其他一些其他细节。
重点是,实际上使用的内存并不重要。但是很多不同的部分必须适应这个记忆空间。由于它们没有紧密地包装在它的一端,它们片段内存空间。想象一下,为简单起见,您的可执行文件被映射到此内存空间的中间。这将你的3GB分成两个1.5GB的块。现在假设您加载了两个动态库,它们将这两个块细分为四个750MB。然后你有几个线程,每个线程需要更多的内存块,进一步分割剩余的区域。当然,实际上每个都不会放在每个连续块的确切中心(这是一个非常愚蠢的分配策略),但是,所有这些内存块都细分了可用的内存空间,切断了它分成许多小块。
您可能有600MB内存空闲,但很可能没有600MB 连续内存可用。因此,单个600MB分配几乎肯定会失败,六个100MB分配可能会成功。
对于您可以分配的内存大小没有固定的限制。答案是“它取决于”。这取决于进程内存空间的精确布局。但是在32位机器上,你不可能在一次分配中分配500MB或更多。