2016-08-01 41 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