C++数组大小的x86和x64的

问题描述:

简单的问题,我在书面方式,需要打开巨大的图像文件(8kx8k)中的程序,但我对如何初始化巨大的阵列在C来保持图像的有点困惑++ 。C++数组大小的x86和x64的

我一直在尝试这样的事:

long long SIZE = 8092*8092;  ///8096*8096 
double* array; 
array = (double*) malloc(sizeof(double) * SIZE); 
if (array == NULL) 
{ 
    fprintf(stderr,"Could not allocate that much memory"); 
} 

但有时我NULL检查没有赶上该数组没有初始化,任何想法,为什么?

而且在X64的机器了12 GB的RAM,任何想法,为什么运行的时候,我不能初始化超过2个或3个数组,甚至?

我真的希望不要有代替阵列的部分工作。欢迎任何帮助。

谢谢。

+0

如果您在Windows下,请查看Address Windowing Extensions:http://msdn.microsoft.com/en-us/library/aa366527(VS.85).aspx – Artelius 2009-10-19 11:29:09

+3

注意:'malloc'是C方式分配内存,在C++中你应该使用'new'。 – Jesper 2009-10-19 11:41:52

+5

可能是一个错字,但仍然是:“8k”应该可能是8 * 1024,即8192.“8096”的读法类似于4k(4096)和8k的混合。 – unwind 2009-10-19 11:43:32

你编译应用程序作为32位应用程序(在Visual Studio中的默认,如果这是你使用的是什么),或作为64位应用程序?如果您将其构建为64位应用程序,则不应该有麻烦。

malloc分配(保留内存并返回一个指针),calloc初始化(将全部零写入该内存)。

+0

BINGO!谢谢。 :-D – StfnoPad 2009-10-19 14:11:33

您可能会运行到2GB的每个进程的地址空间限制,如果你正在运行32位操作系统。用几百MB的系统库和其他东西,以及2或3个512MB的数组,这将容易得到2GB。一个64位的操作系统将帮助你。

+0

“...即使在具有12 GB RAM的x64机器中运行”-1 – sbi 2009-10-19 11:51:56

+1

硬件是否为x64无关紧要。如果操作系统是32位,每进程地址空间为32位,即使它使用PAE来运行一打2GB进程,每个进程仍然限制在2GB的限制内。 – ndim 2009-10-19 11:55:47

+0

他有12GB的系统内存,我敢打赌他已经在使用64位操作系统。 – AntonioMO 2009-10-19 12:07:04

你没有运行到一个数组的大小问题。 8K * 8K仅为64M。即使64M双打(sizeof == 8)也不是问题;那只需要512 MB。现在,一个32位应用程序(无论它在哪里运行)应该能够分配其中的一些。不是8,因为操作系统通常需要为自己保留一些空间(通常略高于2GB),有时甚至在内存碎片时不会保留3。

的“malloc的失败,但没有返回NULL”的行为是Linux配置错误,通过# echo 2 > /proc/sys/vm/overcommit_memory

+0

是的,它是每个阵列512 MB。最后我发现错误,我正在使用Visual Studio 2008 C++进行编译,并且在x86而不是x64下进行编译。虽然vista如何检查NULL是很奇怪的,但我想这也是Windows Vista中的一个bug。 : -/-------几乎给了你正确的答案,但决定把它交给digitalarbeiter,因为他提醒我不要继续混用C++。不管怎么说,还是要谢谢你。 – StfnoPad 2009-10-19 14:09:09

+0

Vista不需要检查,你这样做。 Linux的错误实际上是一个错误,即malloc返回一个非NULL指针,尽管分配内存失败。这意味着即使是正确的程序也不能检查'malloc'是否成功。 – MSalters 2009-10-20 07:48:45

似乎是,你必须在C运行时这样的尺寸没有连续的内存块(500MB的〜)固定堆。尝试将图像映射到进程地址空间,而不是将文件复制到内存中。您只能映射文件的必要部分。

的malloc()未初始化的内存,它只是保留它。你必须明确地初始化它,例如通过从string.h中的memset():

array = (double*) malloc(SIZE * sizeof(double)); 
if (array) memset(array, 0, SIZE * sizeof(double)); 

然而,在C++中应该使用新代替的malloc

double* array = new double[SIZE]; 
if (!array) { 
    cerr << "Could not allocate that much memory" << endl; 
} 
for (int i=0; i<SIZE; i++) array[i] = 0.0; 

关于尺寸:每个这样的阵列为512 MB。你肯定确定你需要双精度(这意味着图像具有64位像素深度)?也许浮动就足够了?这会减少内存占用量。

+0

是否有任何理由在C中使用'memset'并在C++中使用循环? – 2009-10-19 12:31:22

+0

感谢提醒我不要将c与C++混合使用:-D – StfnoPad 2009-10-19 14:09:54

+0

实际上,malloc与使用数组一样多的C++ ...在C++中,您显然会使用一个向量来执行此类任务:std :: vector array( SIZE,0.0); //然后你只需要抓住std :: bad_alloc – 2009-10-19 15:16:38

我真的希望不要有代替阵列的部分工作。欢迎任何帮助。

你有没有看着内存映射文件?

是的,听起来很像堆碎片,为Kirill pointed out。另请参见:How to avoid heap fragmentation?

正如一个侧面说明:虽然你不想打扰整个图像在内存不是一次,有理由不这样做。也许想想一个抽象,让你只保留当前需要的内存块。然后程序代码可以被编写为对内存问题一无所知。

我建议使用压缩。解压缩它的一部分,您需要在代码中进行处理,并在部件完成后进行压缩。

第二个建议:编写代码来重载内存指针“operator +”和“operator-”,以便可以使用非连续内存缓冲区。使用较小的内存缓冲区会使您的代码比连续较大的代码更稳定。我曾经体验过它,并写过一些运算符重载,例如http://code.google.com/p/effoaddon/source/browse/trunk/devel/effo/codebase/addons/mem/include/mcur_i.h。当我在x86_64上测试47G malloc()ed系统内存时,我为malloc()调用分配了1G,所以我总共分配了47个内存块。编辑:虽然如果我试图通过只使用一个malloc()尽可能多地分配,我只会在48G系统上获得30G,也就是说不到70%,这是因为每个malloc()要求更大的缓冲区,更多的管理内存由系统/ libc本身消耗,您知道,我调用了mlock()来防止将分配的内存换出到磁盘。

第三个:尝试posix文件映射,映射到每个映像的内存。 (通过编写C++调用malloc()比new()更稳定,因为当内存受到压力时,new()容易抛出异常而不是返回NULL。