1

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.

StfnoPad
  • 1,037
  • 3
  • 15
  • 25
  • If you're under Windows, look at Address Windowing Extensions: http://msdn.microsoft.com/en-us/library/aa366527(VS.85).aspx – Artelius Oct 19 '09 at 11:29
  • 3
    note: `malloc` is the C way of allocating memory, in C++ you should use `new`. – Jesper Oct 19 '09 at 11:41
  • 5
    Probably a typo, but still: "8k" should probably be 8 * 1024, i.e. 8192. "8096" reads like a mix of 4k (4096) and 8k. – unwind Oct 19 '09 at 11:43
  • What do you mean "that the array was not initialized"? Malloc doesn't initialize the memory it allocates. You have to do that yourself. – jalf Oct 19 '09 at 12:11
  • Ups, yes it is 8092, thanks unwind for spotting the error. This is what happens when you rush to post a question before leaving for lunch. – StfnoPad Oct 19 '09 at 14:02

9 Answers9

4

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
  • 173,980
  • 10
  • 155
  • 350
  • 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 Oct 19 '09 at 14:09
  • 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 Oct 20 '09 at 07:48
4

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
  • 2,295
  • 14
  • 16
  • Is there any reason you used `memset` in C and a loop in C++? – Nathan Fellman Oct 19 '09 at 12:31
  • Actually, malloc is as much C++ as using an array... in C++ you would obviously use a vector, for such a task: std::vector array(SIZE, 0.0); // Then you just have to catch a std::bad_alloc – Matthieu M. Oct 19 '09 at 15:16
3

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
  • 35,870
  • 12
  • 47
  • 57
  • "...even when running in a x64 machine with 12 GB of RAM" -1 – sbi Oct 19 '09 at 11:51
  • 1
    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 Oct 19 '09 at 11:55
  • He has 12GB of RAM in the system, I bet he is already using a 64bit OS. – AntonioMO Oct 19 '09 at 12:07
  • 2
    With 64bit OS you will get 4Gb limit. One should as well use 64bit compiler. – Kirill V. Lyadvinsky Oct 19 '09 at 12:08
  • Yes, it is no use to have a x64 machine if you forget to compile in x64 too. :-/ haha – StfnoPad Oct 19 '09 at 14:10
2

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
  • 109,094
  • 6
  • 73
  • 101
1

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
  • 97,037
  • 24
  • 136
  • 212
1

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
  • 40,723
  • 12
  • 105
  • 192
0

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
  • 219,715
  • 46
  • 258
  • 445
0

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

Community
  • 1
  • 1
Reunanen
  • 7,921
  • 2
  • 35
  • 57
0

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_i.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.

Test
  • 1,697
  • 1
  • 11
  • 10