2014-05-04 30 views
2

我已經檢測到我的程序中的錯誤在負載測試期間和調查。乍一看,我認爲我的代碼有錯誤。然而,它只適用於較少量的數據,並能按照預期的步驟逐步執行。所以我將我的代碼縮減到了下面的示例中。有沒有處理,只是分配:分配所有的記憶讓我的系統崩潰

void main(void) { 
    const signed int n = 100000000; /* high on purpose */ 
    signed int k; 
    char **Buffer = NULL; 

    Buffer = (char**) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, n * sizeof(char*)); 
    if (!Buffer) { 
     printf("Fail to allocate the big buffer\n"); 
     return; 
    } 
    for (k = 0; k < n; ++k) { 
     Buffer[k] = (char*) HeapAlloc(GetProcessHeap(), 0, 3 * sizeof(char)); /* using malloc also causes failure */ 
     if (Buffer[k] == NULL) { 
      printf("Out of memory on buffer no. %d\n", k); 
      /* break; */ 
     } 
    }  
    /* break point here */ 
    for (--k; k >= 0; --k) 
     if (Buffer[k]) 
      HeapFree(GetProcessHeap(), 0, Buffer[k]); 
    HeapFree(GetProcessHeap(), 0, Buffer); 
} 

該電腦的RAM 12Go,沒有頁面文件(交換)。當我運行這段代碼時,內存消耗會像預期的那樣增加,直到我沒有更多的內存可用。最終的配置往往會更慢,然後開始失敗。之後,我的程序和其他應用程序崩潰,包括Windows(7 SP1 64位)和我的調試器(Visual Studio 2013)。 我不能使用break語句,因爲代碼將被放入OpenMP塊(我將使用一個標誌)。不過,我測試過,它沒有改變任何東西。

任何想法,爲什麼它使一切崩潰?

這是我的猜測。當我分配大量少量內存的實例時,我可能會遇到空閒頁面爲零(非常接近)的情況。所以其他應用程序也不能分配內存,即使只有少量內存。他們可能無法很好地處理缺乏記憶,要麼絕對需要,要麼崩潰。 Visual Studio或Windows可能會擔心並在崩潰時崩潰我的應用程序。一旦我與PAGE_FAULT_IN_NONPAGED_AREA錯誤BSD。

我的猜測正確的是導致事故的原因,還是我錯過了什麼?我的代碼是錯誤的還是有一個我不知道的已知錯誤?

我真正的代碼接收一個輸入,處理它並存儲它。這是循環輸入的用戶。這個例子告訴我,檢測分配失敗並不是正確的方法,因爲它已經太晚了。還有你有什麼想法如何防止這種情況?在每次分配之前檢查空閒內存量肯定會導致性能下降。

另外,是不是操作系統應該保留空閒內存的儲備,以防止單個程序消耗所有這些?

這看起來像一本教科書的案例。但是,我無法找到任何類似的代碼導致該錯誤。

+0

當高IRQ中的驅動程序請求已分頁的代碼時,會發生'PAGE_FAULT_IN_NONPAGED_AREA'。或者在這種情況下最有可能卸載。在Windows上關閉分頁有非常奇怪的影響,我強烈建議不要這樣做。 – Mgetz

回答

1

內存管理行爲會因操作系統而異。我不熟悉在Windows 7操作系統中實現的內存管理單元,但是當發生資源匱乏時,您幾乎無法做到(從內核角度來看)。通常,操作系統寧願殺死請求大量資源的進程,這可能是您的情況。

你已經指出了「保留區域」行爲,但即使它已經實現,這也不能解決問題,因爲如果區域被保留,你仍然需要決定哪些進程將使用它,哪些進程將使用它進程不會,導致不允許使用它的進程餓死(並停止)。當然,內核應該是足夠的切割刀保留內存到它自己的程序,以防止自身崩潰(所以我不知道爲什麼windows內核崩潰,但正如我指出的那樣,我不熟悉它的實施)。

我建議您從操作系統的角度閱讀一些關於內存管理(特別是關於Windows內存管理)的論文或書籍。這將爲您進一步研究提供一些線索。

希望這會有所幫助。

+0

謝謝你回答這些問題。 – Plantaquatix