2016-08-01 47 views
2

我正在开发32位OSGEarth项目,我必须将选择的图像拼接成一个大图像。切换到64位不是一个选项。分配大于32位的堆内存允许

图像作为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位的限制?

+4

*切换到64位是不是一种选择* - 你不能挤血掉石头的。也许是时候重新考虑了? – PaulMcKenzie

+0

“当OSGEarth试图分配比32位系统更多的内存时,问题就出现了。”你的意思是3GiB以上? – ysdx

+0

我正在处理地球的高分辨率地图。图像本身往往较小,但OSG要求的数据确实高达千兆字节。 – Acorn

回答

5

内存真正分配在一个连续的块吗?

没有保证。每次你打电话给你时,你都会得到一块内存中的任何内存块。你有效地做的是创建一个链表,链表不是连续的。

如果你需要连续的内存,并限制在32位,那么你真的不能做任何事情。您可能能够捕捉到异常(如果出现异常)并向用户报告要创建的图像很大。

+0

这就是我所害怕的。通过使用osg :: Image,我看不到任何东西可以让我传递大量数据,并告诉它数据不是连续的。开会的时间! – Acorn

0

在您的示例代码中,您不检查new的结果是否抛出bad_alloc异常。

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

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

+3

'new'不返回'nullptr'。它引发一个异常。 – milleniumbug

+0

我想到了这一点,将两幅图像拼接在一起。它可以工作,但随后会出现另一个问题。稍后,图像将缩小(我们正在处理高分辨率的地图)。 我不认为有可能将图像缩小到最大,因为我们的存储空间有限。 – Acorn

+0

为什么你不能缩放图像件呢?或先缩放瓷砖然后缝合?缩放是一种线性操作。 – ilya1725

1

对于Windows,存储器提供给32位可执行默认情况下,限制为2GB,即使在64位Windows中运行。允许使用高达4GB的32位应用程序(特别是如果在64位运运行),设置/LARGEADDRESSAWARE MSVC链接器标志(背后的原因是,“不知道”程序可以处理“负”的地址错了,当然只如果编程不好,例如涉及指针/整数转换)。

注意,该标志可甚至在现有的可执行改变 - 它是在EXE报头中的屏蔽标志。可以用DUMPBIN检查,并与EDITBIN(均配备了MSVC)改变,例如参见这里:http://gisgeek.blogspot.de/2012/01/set-32bit-executable-largeaddressaware.html