2013-09-28 56 views
2

我需要分配一個相當大的內存塊(或多塊) - 幾千兆字節。但是,如果我嘗試分配一個浮動陣列超過5.32元素(〜2 GB),我得到一個運行時錯誤:動態內存分配的限制

terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc

這是確定的:

float* d = new float[532000000]; 

但這是壞的(bad_alloc的除外):

float* d = new float[533000000]; 

然後我試圖分配另一個陣列除了第一個。發現第二個float陣列的最大尺寸爲元件(〜748Mb)。

這是確定的:

float* d = new float[532000000]; 
float* e = new float[196000000]; 

這是不好:

float* d = new float[532000000]; 
float* e = new float[197000000]; 

我想知道什麼是在應用程序中分配的內存的限制,以及如何避免呢?如何使用虛擬內存?

我的系統 - 32位的Ubuntu 12.10,編譯器 - GCC 4.7,內存 - 8GB(〜6.5 GB可用)

+0

您正在32位或64位平臺上運行嗎? –

+0

看起來像一個地址空間碎片問題。這強烈暗示它是一個32位平臺。 – Mysticial

+0

@OliCharlesworth,32位(添加到主題) – gorill

回答

5

你打的虛擬地址空間的限制;即使您有足夠的物理RAM(即操作系統可能可以通過PAE訪問,使用36位指針),但在32位系統上,每個進程仍具有32位虛擬地址空間,這意味着每個進程都無法映射在內存中超過4 GB的內存。

由於通常將虛擬地址空間的上半部分(或上部1 GB,它依賴於內核設置)保留給內核,因此通常將分配限制設置爲〜2 GB,虛擬地址空間碎片可以降低這個數字。

有各種解決方法(例如,在Windows上,可以使用大於4 GB的內存映射文件,一次只能映射其中的一部分;可能在Linux上也可以這樣做),但目前最簡單解決方案就是轉移到64位操作系統並重新編譯64位應用程序。

+0

*移動到64位操作系統*如果進程仍然是32位,這是否工作? –

+0

@ ta.speot.is:它可以給它多一點的呼吸空間(操作系統的東西被移動到上半部分的64位虛擬地址空間,所以用戶進程可以佔用完整的32位虛擬地址空間),但是實際上64位地址空間的好處是你必須重新編譯64位程序。 –

+0

64位系統有沒有限制?我可以使用所有可用的物理內存嗎? – gorill