2016-04-09 153 views
-2

我被教導說,如果你做malloc(),但你沒有free(),內存將保持採取,直到重新啓動發生。那麼,我當然會測試它。一個非常簡單的代碼:C malloc和免費

#include <stdlib.h> 

int main(void) 
{ 
    while (1) malloc(1000); 
} 

我觀察過它Task ManagerWindows 8.1)。

那麼,該程序佔用了2037.4  MB真的很快,並且就這樣堅持下去。我知道這可能是Windows限制程序。

但是這裏有個奇怪的部分:當我關閉控制檯時,儘管我被教導說它不應該這樣,但是內存使用率下降了。

調用free是多餘的,因爲操作系統將它釋放了嗎?

(超過here的問題是相關的,但並不完全回答我是否應該釋放與否。)

+3

想象一下運行很久的程序---就像你的瀏覽器---並且使用大量的線程。如果每個線程每個網頁發生一兆字節的內存泄漏(例如),想象一下在一天之後會發生什麼。 你應該使用'free'。這是很好的做法。 – blazs

+2

如果內存存在於進程的生命週期中,那麼是的OS會爲你做。但很少有記憶應該/需要在整個生命週期中生活。 – user3528438

+2

http://stackoverflow.com/q/2215259/1606345 –

回答

5

在Windows上,32位進程只能分配2048兆字節,因爲那是多少個地址。有些內存可能被Windows顛倒過來,因此總體數字較低。當它失敗時,malloc返回一個空指針,這可能是在這一點發生的。你可以修改你的程序是這樣地看到:

#include <stdlib.h> 
#include <stdio.h> 

int main(void) 
{ 
    int counter = 0; 
    while (1) { 
     counter++; 
     if (malloc(1000) == NULL) { 
      printf("malloc failed after %d calls\n", counter); 
      return 0; 
     } 
    } 
} 

現在你應該得到的輸出是這樣的:

$ ./mem 
malloc failed after 3921373 calls 

進程終止時,或當它從外部終止(如您做通過任務管理器殺死它),釋放該進程分配的所有內存。操作系統管理哪些內存屬於哪個進程,因此可以在進程終止時釋放內存。然而,操作系統並不知道每個進程如何使用它從操作系統請求的內存,並且取決於告訴它何時不再需要內存塊的進程。

爲什麼你需要free()呢?那麼,這隻發生在程序終止時,並且不會區分你仍然需要的內存和不再需要的內存。當你的過程做了複雜的事情時,它經常不斷地爲自己的計算分配和釋放內存。使用free()明確釋放內存非常重要,否則您的進程可能在某個時候不再能夠分配新的內存和崩潰。在可以的時候釋放內存也是很好的編程習慣,所以你的過程不會不必要地消耗大量內存。相反,其他進程可以使用該內存。

4

最好是叫你free與您已經分配的內存中完成後,你可能稍後在程序中需要此內存空間,如果沒有用於新分配的內存空間,則會出現問題。 你應該總是尋求代碼的可移植性。如果Windows釋放這個空間,可能是其他操作系統不這樣做。

1

操作系統中的每個進程都有一定量的可尋址內存,稱爲進程地址空間。如果分配了大量的內存,並且最終分配了可用於此進程的所有內存,malloc將失敗並返回NULL。而且你將無法再爲這個過程分配內存。

+0

你錯過了這個問題的關鍵。我知道操作系統限制了進程的內存,我問的是自動清理。 –

+0

@AmitGold不,你不知道操作系統限制進程內存,否則你不會問這個問題。而你的問題是重複的,並在兩秒鐘內找到谷歌。 (http://stackoverflow.com/questions/2215259/will-malloc-implementations-return-free-ed-memory-back-to-the-system) –

0

使用所有非平凡的操作系統,進程資源在進程終止時由操作系統回收。

除非有specifc和壓倒一切的理由明確終止時可用內存,你不需要做出來,你不應該嘗試至少這些原因:

1)你需要編寫代碼做它,並測試它,並調試它。爲什麼要這樣做,如果操作系統能做到這一點?這不僅僅是多餘的,它會降低質量,因爲你釋放資源的時間永遠不會像操作系統已經發布之前那樣獲得儘可能多的測試。

2)具有複雜的應用程序,具有圖形用戶界面和許多子系統和線程,乾淨地釋放在關機記憶的日子近了,就不可能無論如何,這會導致:

3)許多圖書館開發商已經給出了'你必須明確地釋放blah ...'口頭禪,因爲複雜性會導致lib永遠不會被釋放。許多人報告說,(但不是丟失),對valgrid的記憶,以及對不透明的庫,你無能爲力。

4)您不得釋放正在運行的線程正在使用的任何內存。要在多線程應用程序中安全釋放所有此類內存,您必須確保所有進程線程都已停止並且無法再次運行。用戶代碼沒有這樣做的工具,操作系統。因此不可能在這些應用程序中以任何安全的方式從用戶代碼中明確地釋放內存。

5)操作系統可以以大塊的方式釋放進程內存 - 比在C管理器中混淆數十個子分支要快得多。 6)如果由於內存管理問題而導致進程因爲失敗而終止,那麼多次調用free()根本不會有任何幫助。

7)許多老師和教授都說你必須明確地釋放記憶,所以這顯然是一個不好的計劃。