C ++数组大小x86和x64

时间:2009-10-19 11:17:33

标签: c++ arrays x86 64-bit dynamic-arrays

简单的问题,我正在编写一个需要打开大图像文件(8kx8k)的程序,但我对如何初始化庞大的数组以保存c ++中的图像感到困惑。

我一直在尝试这样的事情:

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检查没有发现数组没有被初始化,任何想法为什么?

此外,我无法初始化更多的2或3个阵列,即使在具有12 GB RAM的x64机器中运行,也不知道为什么?

我真的希望不必使用数组的部分。欢迎任何帮助。

感谢。

9 个答案:

答案 0 :(得分:4)

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

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

修复

答案 1 :(得分:4)

malloc()没有初始化内存,只是保留它。您必须明确初始化它,例如来自string.h的memset():

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

但是,在C ++中,您应该使用 new 而不是 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位像素深度)?也许漂浮就足够了?这样可以减少内存占用。

答案 2 :(得分:3)

如果您运行的是32位操作系统,则可能会遇到每个进程2GB的地址空间限制。有几百MB的系统库和其他东西,以及2或3个512MB的阵列,这将轻松提供2GB。 64位操作系统可以帮助你。

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

似乎在C运行时堆中没有这种大小(~500Mb)的连续内存块。而不是将文件复制到内存中尝试将图像映射到进程地址空间。您只能映射文件的必要部分。

答案 5 :(得分:1)

正如旁注:虽然你不想打扰关于整个图像不能同时存在于内存中,但有理由不这样做。也许考虑一种抽象,它允许你只保留内存中当前需要的块。然后可以编写程序代码,好像不知道内存问题。

答案 6 :(得分:0)

  

我真的希望不必使用数组的部分。欢迎任何帮助。

您是否查看了内存映射文件?

答案 7 :(得分:0)

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

答案 8 :(得分:0)

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

第二个建议:编写代码来重载内存指针“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()来防止分配的内存被换出到磁盘。

第3个:尝试posix文件映射,映射到每个映像的内存。

顺便说一下:调用malloc()比new()更稳定,虽然编写c ++,因为当内存受到压力时,new()很容易出现异常而不是返回NULL。