Acorn
Acorn

Reputation: 1165

Allocating heap memory greater than 32-bit allows

I am working on a 32-bit OSGEarth project, where I have to mosaic a selection of images together into one large image. Switching to 64-bit is not an option.

Images are stored in-memory as a collection of 256x256 tiles. The problem arises when the user attempts to create a single image from many tiles, OSGEarth internally attempts to allocate more memory than a 32-bit system will allow.

I'm attempting to get around this limitation by allocating several chunks of data, each sized 1025 bytes. The 1025'th byte will then "point" to the beginning of the next chunk, with the last byte being a nullptr.

This is what I am currently doing (I plan to allocate much more in the future):

unsigned char* start = new unsigned char[1025];
unsigned char** head = &start;
unsigned char** tail = head + 1025;

for (unsigned int i = 0; i < 3; ++i)
{
    auto c = new unsigned char[1025];
    *tail = &c[0];
    tail = &c + 1025;
}

memset(head, 'C', 1025 * 4);

However, I have some reservations if what I am expecting to happen is actually happening. Is the memory truly allocated in one, contiguous block? If not, then my memset is writing over unallocated data, which could be bad.

Is there any way around the 32-bit limitations?

Upvotes: 2

Views: 358

Answers (3)

ilya1725
ilya1725

Reputation: 4938

In your sample code you don't check the result of new for throwing a bad_alloc exception.

Is the error occurs when the user wants the final image to be larger than memory? Is the requirement to keep the final image in memory fixed? What algorithm do you use to stitch the tiles together?

I had a similar problem while working on an embedded system with 32MB of RAM. A possible solution may be to keep the final image as a file on disk and keep in memory only enough information to stitch the next tile. It is more time consuming than just allocating one giant block in memory, but now you are limited by your disk size, not 32-bit address space (and you get a performance hit, of course).

Upvotes: 0

EmDroid
EmDroid

Reputation: 6066

For Windows, memory available to a 32-bit executable is limited to 2GB by default, even if run under 64-bit Windows. To allow use up to 4GB for 32-bit app (especially if running under 64-bit Win), set the /LARGEADDRESSAWARE MSVC linker flag (the reason behind is that the "unaware" program might handle "negative" addresses wrong, of course only if programmed badly, e.g. pointer/integer conversions involved).

Note that this flag can be changed even in an existing executable - it is a mask flag in the EXE header. Can be checked with dumpbin and changed with editbin (both come with MSVC), see for example here: http://gisgeek.blogspot.de/2012/01/set-32bit-executable-largeaddressaware.html

Upvotes: 1

NathanOliver
NathanOliver

Reputation: 180500

Is the memory truly allocated in one, contiguous block?

There is no guarantee. Every time you call new you could be given a block of memory that is anywhere in memory. What you are effectively doing is creating a linked list and linked list are not contiguous.

If you need contiguous memory and are limited to 32 bits then there really isn't anything you can do. You might be able to catch the exception(if one is surfaced) and report to the user that the image is to large to be created.

Upvotes: 5

Related Questions