1

简单的问题,我正在编写一个需要打开巨大图像文件(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 检查没有发现数组没有初始化,知道为什么吗?

此外,即使在具有 12 GB RAM 的 x64 机器上运行,我也无法初始化超过 2 个或 3 个数组,知道为什么吗?

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

谢谢。

4

9 回答 9

4

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

“malloc failed but didn't return NULL”的行为是一个Linux配置错误,由# echo 2 > /proc/sys/vm/overcommit_memory

于 2009-10-19T11:46:39.363 回答
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 位像素深度)吗?也许一个浮点数就足够了?这将使内存占用量减半。

于 2009-10-19T11:52:39.090 回答
3

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

于 2009-10-19T11:39:48.910 回答
2

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

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

于 2009-10-19T12:00:30.340 回答
1

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

于 2009-10-19T11:47:58.003 回答
1

顺便说一句:尽管您不想担心整个图像不会立即出现在内存中,但有理由不这样做。也许考虑一个抽象,允许您仅将当前需要的块保留在内存中。然后可以编写程序代码,就好像不知道内存问题一样。

于 2009-10-19T12:02:56.780 回答
0

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

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

于 2009-10-19T11:53:21.973 回答
0

是的,正如基里尔指出的那样,听起来很像堆碎片。另请参阅:如何避免堆碎片?

于 2009-10-19T11:55:43.447 回答
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() 来防止分配的内存被换出到磁盘。

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

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

于 2009-10-19T12:05:16.563 回答