分配大于32位的堆内存允许

时间:2016-08-01 19:22:03

标签: c++ memory memory-management openscenegraph

我正在开发一个32位OSGEarth项目,我必须将选择的图像拼接成一个大图像。切换到64位不是一种选择。

图像作为256x256图块的集合存储在内存中。 当用户尝试从许多磁贴创建单个映像时,问题就出现了,OSGEarth内部尝试分配的内存比32位系统允许的内存多。

我试图通过分配几个数据块来解决这个限制,每个数据块大小为1025字节。然后第1025个字节将指向"指向"到下一个块的开头,最后一个字节是nullptr。

这就是我目前正在做的事情(我计划将来分配更多):

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

然而,如果我真正想要发生的事情,我有一些保留意见。内存是否真正分配在一个连续的块中?如果没有,那么我的memset正在写未分配的数据,这可能是坏的。

有没有解决32位限制的方法?

3 个答案:

答案 0 :(得分:5)

  

内存是否真正分配在一个连续的块中?

无法保证。每次调用new时,都可以获得内存中任何位置的内存块。你实际做的是创建一个链表,链表不是连续的。

如果您需要连续的内存并且限制为32位,那么您无法做任何事情。您可能能够捕获异常(如果有异常)并向用户报告要创建的图像很大。

答案 1 :(得分:1)

对于Windows,默认情况下,32位可执行文件可用的内存限制为2GB,即使在64位Windows下运行也是如此。要允许最多4GB用于32位应用程序(特别是如果在64位Win下运行),请设置/LARGEADDRESSAWARE MSVC链接器标志(背后的原因是&#34; unaware&#34;程序可能处理&#34;否定&#34;地址错误,当然只有编程很糟糕,例如涉及指针/整数转换)。

请注意,即使在现有可执行文件中也可以更改此标志 - 它是EXE标头中的掩码标志。可以使用dumpbin进行检查并使用editbin进行更改(两者都带有MSVC),例如请参见:http://gisgeek.blogspot.de/2012/01/set-32bit-executable-largeaddressaware.html

答案 2 :(得分:0)

在您的示例代码中,您不会检查new的结果是否会引发bad_alloc例外。

当用户希望最终图像大于内存时,是否会发生错误?是否要求将最终图像保留在内存中?你用什么算法将瓷砖拼接在一起?

在使用32MB RAM的嵌入式系统上工作时遇到了类似的问题。一种可能的解决方案可能是将最终图像保存为磁盘上的文件,并在内存中保留足够的信息以拼接下一个图块。它比在内存中分配一个巨大块更耗时,但现在你受到磁盘大小的限制,而不是32位地址空间(当然,你会受到性能损失)。