關於C語言的malloc函數以及記憶體流失的問題

來源:互聯網
上載者:User

malloc函數

malloc函數的原型:

(void *)malloc(int size)

 malloc函數的傳回值是一個void類型的指標,參數為int類型的資料,即申請分配的記憶體大小,單位是位元組。記憶體配置成功之後,malloc函數返回這塊記憶體的首地址,你需要一個指標來接受這個地址。但是由於函數的傳回值是void *類型,所以必須強制轉換成你所接收的類型。也就是說這塊記憶體將來要用來儲存什麼類型的資料,比如 char *p = (char *)malloc(100);

在堆上分配了100個位元組的記憶體,返回這塊記憶體的首地址,把地址強制轉換成char *類型後,賦給char *類型的指標變數p;同時告訴我們這塊記憶體將用來儲存char類型的資料。也就是說你只能通過指標變數p來操作這塊記憶體。這塊記憶體本身沒有名字,對它的訪問是匿名訪問


使用malloc函數同樣要注意這點:如果所申請的記憶體塊大於目前堆上剩餘的記憶體塊(整塊),則記憶體配置就會失敗,函數函數NULL。注意這裡說的是“堆上剩餘記憶體塊”不是所有剩餘記憶體塊之和,因為malloc函數申請的是連續的一塊記憶體。既然malloc函數申請記憶體又不成功的可能,那我們在使用指向這塊記憶體的指標時,必須用if( NULL != p)語句上來驗證記憶體配置確實成功了。




記憶體流失

在C語言程式設計中,記憶體流失幾乎是很難避免的,C程式產生泄漏記憶體,則運行速度會逐漸層慢,並最終停止運行;如果產生覆蓋記憶體,程式會變得非常脆弱,很容易受到惡意使用者的攻擊。記憶體流失是一種隱性危害,它們很難被發現,通常不能在相應的原始碼中找到錯誤,需要仔細分析與專門的偵查工具才能發現。

(1)記憶體流失的定義

通常我們所說的記憶體流失,是指分配出去的記憶體在使用之後沒有釋放掉,沒有回收,長此以往,會造成沒有足夠的記憶體可以分配。一般表現為已耗用時間越長,佔用的記憶體越多,最終導致系統奔潰。一般的記憶體流失是指堆記憶體的泄漏。堆記憶體是指程式從堆中分配的,大小任意的(記憶體塊的大小可以在程式運行期決定),使用完後必須顯式釋放的記憶體。應用程式一般使用malloc,realloc,new等函數從堆中分配到一塊記憶體,使用完後,程式必須負責相應的調用free或delete釋放該記憶體塊,否則,這塊記憶體就不能被再次使用,我們就說這塊記憶體流失了。


(2)記憶體流失的原因

2.1 C語言記憶體配置情況 
  在C語言中,根據資料在記憶體中存在的時間(生存周期)不同,將記憶體空間分為三個區:

1)程式區:用於儲存程式的代碼,即程式的二進位代碼。

2)靜態儲存區:用於儲存全域變數和靜態變數,這些變數的空間在程式編譯時間就已經分配好了。

3)動態儲存裝置區:用於在程式執行時分配的記憶體,又分為:堆區(heap)和棧區(stack)。堆區:用於動態記憶體 分配,程式運行時由記憶體配置函數在堆上分配記憶體。在C語言中,只能使用指標才能動態分配記憶體。棧區:在 函數執行時,函數內部的局部變數和函數參數的儲存單元的記憶體地區,函數運行結束時,這些記憶體地區會自動釋 放。 
  2.2 C語言動態記憶體分配 
  在C語言中用記憶體配置函數來實現記憶體的動態分配,這些函數有:malloc()和realloc()等函數。malloc():使用這個 函數時需要包含標頭檔。使用該函數需要指定要分配的記憶體位元組數作為參數,例如: 
  int *pNumber=(int *) malloc(100) 
  這條語句分配了100個位元組的記憶體,並把這個記憶體塊的地址賦給pNumber,這個記憶體塊可以儲存最大25個int值, 每個int佔4個位元組。如果不能分配請求的記憶體,malloc()會返回一個null指標。 
  2.3 釋放動態分配的記憶體 
  堆上分配的記憶體會在整個應用程式結束之後,由作業系統負責回收,但最好是在使用完這些記憶體後立即釋放。如 果不釋放,會引起記憶體流失,極大佔用系統資源,可能會產生各種未知的錯誤。所以,必須使用free()函數釋 放記憶體,參數是記憶體位址(指標),例如:free(pNumber),依上例。 

(3)記憶體流失避免的方法 

3.1正確使用malloc函數分配記憶體 
  malloc是一個函數,專門用來從堆上分配記憶體。使用malloc函數需要幾個要求:記憶體配置給誰。分配多大記憶體。 是否還有足夠記憶體配置。 記憶體將用來儲存什麼格式的資料。分配好的記憶體在哪裡。 如果這5點都確定,那記憶體就 能分配。下面看看malloc的原型:(void *)malloc(int size) 
  malloc函數的傳回值是一個void類型的指標,參數為int類型的資料,即申請分配的記憶體大小,單位是位元組。記憶體 分配成功之後,malloc函數返回這塊記憶體的首地址,你需要一個指標來接受這個地址。也就是說這塊記憶體將來要 用來儲存什麼類型的資料,如: 
  char *p = (char *)malloc(100) 
  在堆記憶體配置了100個位元組的記憶體,返回這塊記憶體的首地址,把地址強制轉換成char *類型後賦給char *類型的指 針變數p;同時告訴我們這塊記憶體將用來儲存char類型的資料。你只能通過指標變數p來操作這塊記憶體,這塊記憶體 本身沒有名字,對它的訪問是匿名訪問。但是,不一定每次malloc函數都能成功分配到記憶體。既然malloc函數申 請記憶體存在不成功的可能,那我們在使用指向這塊記憶體的指標時,必須用if( NULL 。= p)語句上來驗證記憶體分 配確實成功了。 


  3.2 正確使用free函數釋放記憶體 
  既然有分配,那就必須有釋放,不然的話,有限的記憶體就會用光,而沒有釋放的記憶體卻佔用空間,與malloc對應 的就是free函數了。free函數只有一個參數,就是所要釋放的記憶體塊的首地址(指標)。按上例,則 為:free(p).free函數其實它就做了一件事:斬斷指標變數和這塊記憶體的對應關係。free函數就是把這塊記憶體和p 之間的關係斬斷;p本身的值並沒有改變或者消失,即指標變數p本身儲存的地址並沒有改變,那塊被釋放的記憶體 裡面儲存的值也沒有改變。這就是free函數的功能,一個malloc對應一個free,是一夫一妻制。在使用free(p) 函數記憶體釋放後,指標變數p本身儲存的地址並沒有改變,那我們必須需重新把p的值變為NULL:p = NULL。如 果沒有把該指標置NULL,這個指標就成為了“懸null 指標”,這是很危險的,且也是經常出錯的地方。 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.