2010-08-17 87 views
2

我正在編寫一個程序來泄漏內存(主內存)來測試系統如何與低系統內存和交換內存的行爲。我們使用下面的循環週期性運行,並出現內存泄漏內存泄漏使用malloc失敗

main(int argc, char* argv[]) 
{ 
    int arg_mem = argv[1]; 

     while(1) 
     { 
      u_int_ptr =(unsigned int*) malloc(arg_mem * 1024 * 1024); 

     if(u_int_ptr == NULL) 
      printf("\n leakyapp Daemon FAILED due to insufficient available memory...."); 

      sleep(arg_time); 
     } 

} 

上述循環運行了一段時間,並打印消息「leakyapp守護進程失敗,因爲可用內存不足......」。但是當我運行「free」命令時,我可以看到運行該程序對主內存或交換沒有任何影響。

我做錯了什麼?

回答

7

只有在實際寫入之前,物理內存纔會提交給您的分配。

如果您2.6.23之後有一個內核版本,使用mmap()MAP_POPULATE標誌,而不是malloc()

u_int_ptr = mmap(NULL, arg_mem * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0); 

if (u_int_ptr == MAP_FAILED) 
    /* ... */ 

如果你有一箇舊的內核,你必須觸及每一頁的分配。

+0

我覺得「不」,在最後一行應刪除:-) – Job 2010-08-17 07:54:20

+0

我改變了我的代碼,因此我宣佈一個陣列來存儲所有指針 的char *一[1000]; 而在while循環 u_int_ptr = MMAP(NULL,arg_mem * 1024 * 1024,PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE,-1,0); A [1] =(字符*)u_int_ptr; //觸摸頁面* a [i] ='A'; i ++; 但我仍面臨着同樣的問題。 – Poorna 2010-08-17 08:13:47

+0

它在內存上執行memset後工作 – Poorna 2010-08-17 16:14:06

0

什麼是ulimit -m -v的打印?

說明:在任何服務器操作系統上,您可以限制進程可以分配的資源量,以確保單個失控進程無法關閉整個計算機。

+0

它顯示 最大內存大小(千字節,-m)無限 虛擬內存(千字節,-v)無限 – Poorna 2010-08-17 07:32:03

+0

在這種情況下,我的回答並不能幫助:-) – 2010-08-17 07:40:36

3

可能有某種寫時複製優化。我會建議實際寫一些東西給你正在分配的內存。

0

我猜(基於命令行參數)你使用的是桌面/服務器操作系統而不是嵌入式系統。

像這樣分配內存可能不會消耗太多內存。您的內存分配可能甚至沒有成功 - 在某些操作系統(例如Linux)上,即使您詢問的內存比可用內存多,malloc()也可以返回非NULL值。

不知道你的操作系統是什麼,也不知道你想要測試什麼,很難建議任何具體的東西,但是你可能想要看看比malloc()更低級別的分配內存的方式,或者控制虛擬內存系統。在Linux上,你可能想看看mlock()

+0

我使用的SUSE Linux企業版。 – Poorna 2010-08-17 07:56:30

0

我想caf已經解釋過了。 Linux通常配置爲允許過度使用內存。你分配了大量的內存,但是內部沒有任何事情發生,只是做了一個說明,你的進程需要這麼大的內存。在您嘗試寫入該塊之前,內核試圖找到免費的虛擬內存以滿足讀/寫訪問。這有點像航班預訂:航班通常是overbook的航班,因爲總有一部分乘客沒有出現。

您可以通過在分配後向memset()寫入塊來強制提交內存。 calloc也應該工作。

1

發生了什麼是malloc從堆中請求argmem * 256頁(假設頁面大小爲4 KB)。堆又從操作系統請求內存。但是,所做的只是在新分配的內存塊的頁表中創建條目。除了堆需要跟蹤malloc請求之外,沒有實際的物理RAM被分配給進程。

只要過程試圖通過讀取寫入訪問其中一個頁面,就會生成頁面錯誤,因爲頁表中的條目實際上是一個懸掛指針。然後操作系統將爲進程分配一個物理頁面。只有這樣你才能看到可用的物理內存下降。

由於所有新頁面開始完全歸零,Linux的可能採用的策略是「寫入時複製」優化頁分配。即它可以保持單個頁面完全歸零,並且當進程試圖從先前未使用的頁面讀取時總是分配該頁面。只有當進程試圖寫入新頁面時,實際上它纔會從物理RAM中分配一個全新的頁面。我不知道Linux是否真的這樣做,但如果是這樣,僅僅從新頁面讀取內容不足以增加物理內存使用量。

所以,最好的策略是分配的內存大塊,然後在它整個4096個字節間隔寫的東西。