2016-12-01 77 views
0

在一堆程序我遇到有關動態內存分配來我總能找到相同的代碼我喜歡當它是需要動態分配內存空間:malloc的返回值,而條件

int *pointer = (int *)malloc(sizeof(int)); 

if(pointer == NULL) 
    exit(1); // or return 1 

// else the program keep running 

我想知道爲什麼它是不使用,或者至少我從來沒有見過它,這樣的事情:

int *pointer 
while((pointer = (int *)malloc(sizeof(int)) == NULL); 

我雖然它和我想出的唯一的事情是,如果你不能分配新的內存,因爲有沒有更多的留在堆上,所以第二個例子會變成無限循環。是對的嗎?因爲如果內存分配由於某些其他原因而失敗(我真的不知道是哪一個),那麼比將內存分配放入循環中可能會解決問題。

我錯過了什麼嗎?哪一個「風格」是首選?

+1

The第二個例子在失敗時確實會變成一個無限循環,而第一個例子會立即退出......是否有一個原因,您更喜歡無限循環到達直接退出?我並不完全確定我理解你的問題...... –

+1

這是否有可能在多線程程序中運行?如果是這樣,可以想象線程1可能無法分配,因爲線程2已經佔用了所有空間。如果線程2隨後釋放它分配的一些空間,那麼線程1可能能夠獲得如此釋放的一些內存 - 然後可能指向重試malloc,可能在嘗試之間存在某種暫停,而不是全速敲擊分配器。否則(單線程程序),重試沒有意義。 –

回答

1

唯一的使用情況下,我能想到的重新嘗試一種失敗的malloc,將是支持陣陣不同的程序內存分配環境中運行的程序,都充分釋放它很快。在這種情況下,一個無法獲得所有必要內存的程序應該等待另一個釋放足夠的內存才能繼續。

但是,這將需要程序員非常謹慎,因爲有一個即時的情況。假設系統有4 GB的免費內存,即沒有內存消耗進程正在運行。假設一個可以獲得1.5GB,並且需要1.5個,另一個也有1.5GB,還需要1.5個。你處於一個很好且乾淨的死鎖,因爲只有1 GB可用,並且兩個進程都在等待另一方釋放任何東西。

即使無法獲取所有必需內存的進程在進入循環之前不得不釋放所有內容,也可能處於競爭狀態,進程只獲取他們所需的部分內容,不能獲取所有內容,釋放並再次循環如果能夠一次全部獲得,則不需要任何處理。

由於我們更喜歡健壯的系統,程序假定內存將可用,並且如果不是,則只是中止。現在是人類選擇增加內存,改變程序讓它使用更少的內存,還是序列化處理只有一個大的程序在同一時間或者更好的問題...

1

由於每malloc手冊頁,malloc可能會失敗,只有一個錯誤,這是ENOMEM,這是內存不足的錯誤。在這種情況下沒有重試的要點。

在while循環重試的風格之後通常是與其他系統調用,如read(2)open(2)select(2)等,其可以返回-1指示錯誤並設置errnoEINTR,這意味着它們因信號而中斷。在這種情況下,您通常會再次嘗試重新撥打電話。

0

如果沒有剩餘內存,它確實會導致您的程序在一個無限繁忙循環中佔用CPU。

如果您的計算機內存不足,我認爲您最後需要的是一些仍留在RAM中的幽靈進程,從而竊取CPU。

最好是程序正常終止並通知用戶它們內存不足。由於內存不足在大多數計算機上是一個相當嚴重的錯誤條件。

這可能會由內存泄漏,堆損壞和其他令您的程序的執行環境不穩定的令人討厭的事情造成。這可能意味着你自己的過程中的錯誤是怪罪。這又意味着該過程本身不會從錯誤狀態中恢復。

0

內存分配失敗時不會重試內存分配,因爲沒有理由期望一旦失敗後,它們將在任何後續嘗試中成功,而且沒有任何更改。正如你所觀察到的,這當然適用於內存不足的情況,但它也適用於你可以想象的任何其他合理的故障模式。畢竟,如果malloc()可以自行恢復,那麼它不會首先出現故障。因此,像你提出的那樣,一個緊密的內存分配循環跟測試分配是否成功完全一樣糟糕。在失敗的情況下,無論失敗的原因如何,程序進入無限循環的可能性很大。