2011-03-17 52 views
13

這是使用G ++ 4.1.2在CentOS 64位上的C++。new []不會減少可用內存直到填充

我們正在編寫一個測試應用程序,以加載系統上的內存使用量n千兆字節。這個想法是整個系統的負載通過SNMP等進行監控。所以這只是一種行使監控的方式。

我們所看到的不過是簡單地做:

char* p = new char[1000000000]; 

不影響如圖頂部或自由-m所使用的內存

內存分配似乎只能成爲「真正的」曾經的記憶被寫入:

memcpy(p, 'a', 1000000000); //shows an increase in mem usage of 1GB 

但我們必須寫入所有的內存,只是寫的第一個元素沒有顯示在使用的內存增加:

p[0] = 'a'; //does not show an increase of 1GB. 

這是正常的,是否已經完全分配了內存?我不確定它是否是我們正在使用的工具(top和free -m),它們顯示的值不正確,或者在編譯器或運行時和/或內核中是否存在某些巧妙的事情。

即使在優化關閉的調試版本中也可以看到此行爲。

這是我的理解,一個新的[]立即分配內存。 C++運行時是否延遲這個實際的分配,直到它被訪問時爲止。在這種情況下,可以將內存不足異常延遲到實際分配內存之後,直到訪問內存爲止?

因爲這對我們來說不是問題,但它會很高興知道爲什麼會發生這種事情!

乾杯!

編輯:

我不想知道我們應該如何使用的載體,這不是OO/C++ /處事等等等等的電流方式,我只是想知道這是爲什麼發生這種事情的方式,而不是對嘗試它的替代方法提出建議。

回答

8

請查閱overcommit。默認情況下,Linux在訪問之前不會保留內存。如果你最終需要更多的內存,你不會得到一個錯誤,但是一個隨機進程會被終止。您可以使用/proc/sys/vm/*來控制此行爲。

IMO,overcommit應該是每個進程設置,而不是全局設置。並且默認不應該過度使用。

+0

這! +1爲正確的答案。 – 2011-03-17 16:10:41

17

當您的程序庫從操作系統分配內存時,操作系統只會在進程的虛擬地址空間中保留一個地址範圍。在您使用之前,操作系統沒有理由實際提供此內存 - 就像您演示的那樣。

如果你看看例如/proc/self/maps你會看到地址範圍。如果你看頂部的記憶使用你不會看到它 - 你還沒有使用它。

+0

我對此有過一些經驗,我認爲現代編譯器中的內存關聯和垃圾收集方法也會影響問題。你有這方面的技術信息嗎? – Hossein 2011-03-17 15:51:37

+0

在C++中沒有垃圾收集 - 它沒有關係。儘管如此,在理論上,Java或C#可能是一個額外的原因。有關詳細信息,請從*虛擬地址空間* – Erik 2011-03-17 15:55:41

+0

上的維基百科頁面開始我認爲這是Unix的一個常見功能。它可能會導致地獄,因爲系統會讓你的應用程序相信它能夠滿足它的請求,但是可能不會處於某個位置,但是在實踐中我認爲它會產生較低的內存消耗。 – 2011-03-17 16:01:06

2

關於你問題的後半部分:

語言標準不允許在拋出bad_alloc的任何延誤。這必須作爲new []返回一個指針的替代方法。它不會晚點發生!

某些操作系統可能會嘗試過量使用內存分配,並在稍後失敗。這不符合C++語言標準。