views:

537

answers:

9

Simple question, I'm writting a program that needs to open huge image files (8kx8k) but I'm a little bit confused on how to initialize the huge arrays to hold the images in c++.

I been trying something like this:

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");
}

But sometimes my NULL check does not catch that the array was not initialized, any idea why?

Also I can't initialize more that 2 or 3 arrays, even when running in a x64 machine with 12 GB of RAM, any idea why?

I would really wish not to have to work with sections of array instead. Any help is welcome.

Thanks.

+3  A: 

You might be running into a 2GB per-process address space limit if you are running a 32bit operating system. With a few hundred MBs of system libs and other stuff, and 2 or 3 arrays of 512MB each, that will give 2GB easily. A 64bit OS would help you there.

ndim
"...even when running in a x64 machine with 12 GB of RAM" -1
sbi
Whether the hardware is x64 or not does not matter. If the operating system is 32bit has a per process address space of 32bit, even if it is using PAE to possibly run a dozen 2GB processes, every process is still limited to its 2GB limit.
ndim
He has 12GB of RAM in the system, I bet he is already using a 64bit OS.
machielo
With 64bit OS you will get 4Gb limit. One should as well use 64bit compiler.
Kirill V. Lyadvinsky
Yes, it is no use to have a x64 machine if you forget to compile in x64 too. :-/ haha
StfnoPad
+4  A: 

You're not running into an array size problem. 8K*8K is merely 64M. Even 64M doubles (sizeof==8) are not an issue; that would require a mere 512 MB. Now, a 32 bit application (no matter where it's running) should be able to allocate a few of them. Not 8, because the OS typically needs to reserve some space for itself (often slightly over 2GB) and sometimes not even 3 when memory is fragmented.

The behavior of "malloc failed but didn't return NULL" is a Linux configuration bug, fixed by # echo 2 > /proc/sys/vm/overcommit_memory

MSalters
Yes it is 512 MB per array. Finally I found the error, I was compiling using Visual studio 2008 c++ and compiling in x86 not x64. Although it is weird how vista fails to check for the NULL, I guess it is a bug in windows vista too. :-/ -------Almost gave you the correct answer but decided to give it to digitalarbeiter because he remind me not to keep mixing c with c++. Thanks Anyway.
StfnoPad
Vista doesn't need to check, you do. The Linux bug is actually a bug where malloc returns a non-NULL pointer despite failing to allocate memory. This means that even a correct program cannot check if `malloc` succeeded.
MSalters
+1  A: 

Seems to be that you have no continuous memory block of such size (~500Mb) in C runtime heap. Instead of copying file into memory try to map image into a processes address space. You could map only necessary parts of the file.

Kirill V. Lyadvinsky
+4  A: 

malloc() does not initialize memory, it just reserves it. You will have to initialize it explicitly, e.g. via memset() from string.h:

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

However, in C++ you should use new instead of 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;

Regarding size: each such array is 512 MB. Are you positively sure you need double precision (which means the image has 64-bit pixel depth)? Maybe a float would suffice? That would halve the memory footprint.

digitalarbeiter
Is there any reason you used `memset` in C and a loop in C++?
Nathan Fellman
Thank for reminding me not to mix c with c++ :-D
StfnoPad
Actually, malloc is as much C++ as using an array... in C++ you would obviously use a vector, for such a task: std::vector<double> array(SIZE, 0.0); // Then you just have to catch a std::bad_alloc
Matthieu M.
A: 

I would really wish not to have to work with sections of array instead. Any help is welcome.

Have you looked into memory-mapped files?

sbi
A: 

Yep, sounds a lot like heap fragmentation, as Kirill pointed out. See also: How to avoid heap fragmentation?

Pukku
+2  A: 

Are you compiling your application as a 32-bit application (the default in Visual Studio, if that's what you're using), or as a 64-bit application? You shouldn't have troubles if you build it as a 64-bit app.

malloc allocates (reserves memory and returns a pointer), calloc initializes (writes all zeros to that memory).

Mr Fooz
BINGO! thanks. :-D
StfnoPad
+1  A: 

Just as a side note: although you don't want to bother about the whole image not being in memory at once, there are reasons not to do it. Maybe think about an abstraction that allows you to keep only the currently needed chunk in memory. The program code then can be written as though ignorant of the memory issues.

xtofl
A: 

i suggest using compression. decompress part of it which you need to process in your code whenever, and compress it after the part done.

2nd proposal: write code to overload memory pointer "operator+" and "operator-" so you could use non-continuous memory buffers. use smaller memory buffers make your code more stable than a continuous larger one. i had experienced it and had written some operator-overloading, see http://code.google.com/p/effoaddon/source/browse/trunk/devel/effo/codebase/addons/mem/include/mcur%5Fi.h for the example. when i test 47G malloc()ed system memory on a x86_64, i allocated just 1G per malloc() call, so i allocated 47 memory blocks in total. EDIT: while if i tried to allocate as much as possible by using just one malloc(), i would only get 30G on a 48G system, say less than 70%, that's because larger buffer per malloc() requested, much more managemental memory consumed by the system/libc itself, you know, I called mlock() to prevent the allocated memory from being swapped out to the disk.

3rd one: try posix file mapping, map to memory per image.

Btw: call malloc() is more stable than new() though writing c++, because when memory got stressed, new() is prone to trow exceptions instead of returning NULL.

EffoStaff Effo