該賬戶是華為云開發(fā)者社區(qū)的官方運營賬戶,提供對云計算的全面、深入的前景分析、豐富的技術干貨、程序樣本、華為云前沿信息共享。
本文由華為云社區(qū)《【云駐共創(chuàng)】C語言中動態(tài)內存分配的本質》,作者:G-washington分享。
C語言是一門面向過程的、抽象化的通用程序設計語言,廣泛應用于底層開發(fā)。盡管C語言提供了許多低級處理的功能,但仍然保持著跨平臺的特性,因為C語言具有可移植性,可拓展性,可重用性等特性,促使C語言仍然在編程語言排行榜上占據(jù)一定有利地位。而C語言中比較重要的就是指針,它可以用來鏈表操作,談到鏈表,很多時候為此分配內存采用動態(tài)分配而不是靜態(tài)分配。
內存分配的概念
通常定義變量(或對象),編譯器在編譯時都可以根據(jù)該變量(或對象)的類型知道所需內存空間的大小,從而系統(tǒng)在適當?shù)臅r候為他們分配確定的存儲空間。這種內存分配稱為靜態(tài)存儲分配;有些操作對象只在程序運行時才能確定,這樣編譯時就無法為他們預定存儲空間,只能在程序運行時,系統(tǒng)根據(jù)運行時的要求進行內存分配,這種方法稱為動態(tài)存儲分配。所有動態(tài)存儲分配都在堆區(qū)中進行。
內存不是取之不盡用之不竭,4g、8g、16g是常見的電腦內存大小,打開任務管理器,能看到不同的應用占據(jù)的內存情況。如果一個應用程序占了大部分內存,估計別的應用就資源緊張了,那這個應用可能會被卸載,找個節(jié)省內存的。
內存管理是計算機接近物理本質的操作,那些程序語言之下的動作,最終都要調動內存來實現(xiàn)。系統(tǒng)的資源不是無限的,系統(tǒng)上運行的程序也不是只有這一個,忽略內存,就會設計出危險的、冗余的代碼產品,或者沒法更好的交互。
動態(tài)內存分配的特點
動態(tài)內存是相對靜態(tài)內存而言的。所謂動態(tài)和靜態(tài)就是指內存的分配方式。動態(tài)內存是指在堆上分配的內存,而靜態(tài)內存是指在棧上分配的內存。動態(tài)內存分配的本質就是,什么時候需要一塊內存的時候,再分配這塊內存;當不再需要某一塊內存的時候,就可以把這塊內存釋放掉。這種靈活的內存分配方式,正好適合鏈表這種數(shù)據(jù)結構。
傳統(tǒng)數(shù)組的缺點
數(shù)組與動態(tài)內存分配相比有以下缺點:
- 數(shù)組的長度必須事先指定,而且只能是常量,不能是變量。
- 因為數(shù)組長度只能是常量,所以它的長度不能在函數(shù)運行的過程當中動態(tài)地擴充和縮小。
- 對于數(shù)組所占內存空間程序員無法手動編程釋放,只能在函數(shù)運行結束后由系統(tǒng)自動釋放,所以在一個函數(shù)中定義的數(shù)組只能在該函數(shù)運行期間被其他函數(shù)使用。
而“傳統(tǒng)數(shù)組”的問題,實際上就是靜態(tài)內存的問題。但是動態(tài)內存就不存在這個問題,因為動態(tài)內存是由程序員手動編程釋的,所以想什么時候釋放就什么時候釋放。只要程序員不手動編程釋放,就算函數(shù)運行結束,動態(tài)分配的內存空間也不會被釋放,其他函數(shù)仍可繼續(xù)使用它。除非是整個程序運行結束,這時系統(tǒng)為該程序分配的所有內存空間都會被釋放。
動態(tài)內存的申請與釋放
動態(tài)內存的申請與釋放主要依靠兩個函數(shù)malloc和free。malloc 是一個系統(tǒng)函數(shù),它是 memoryallocate 的縮寫。其中memory是“內存”的意思,allocate是“分配”的意思。顧名思義 malloc 函數(shù)的功能就是“分配內存”,要調用它必須要包含頭文件<;。
malloc()函數(shù)會向堆中申請一片連續(xù)的可用內存空間;若申請成功 ,,返回指向這片內存空間的指針 ,若失敗 ,則會返回NULL, 所以我們在用malloc()函數(shù)開辟動態(tài)內存之后, 一定要判斷函數(shù)返回值是否為NULL;返回值的類型為void*型, malloc()函數(shù)并不知道連續(xù)開辟的size個字節(jié)是存儲什么類型數(shù)據(jù)的 ,所以需要我們自行決定 ,方法是在malloc()前加強制轉 ,轉化成我們所需類型 ,如: (int*)malloc(sizeof(int)*n).
下面使用 malloc 函數(shù)寫一個程序,程序的功能是:調用被調函數(shù),將主調函數(shù)中動態(tài)分配的內存中的數(shù)據(jù)放大 10 倍。
輸出結果是:*p = 100
free是釋放函數(shù),在堆中申請的內存空間不會像在棧中存儲的局部變量一樣 ,函數(shù)調用完會自動釋放內存 , 如果我們不手動釋放, 直到程序運行結束才會釋放, 這樣就可能會造成內存泄漏, 即堆中這片內存中的數(shù)據(jù)已經(jīng)不再使用, 但它一直占著這片空間, 所以當我們申請的動態(tài)內存不再使用時 ,一定要及時釋放 .不過需要注意的是,釋放并不是指清空內存空間,而是指將該內存空間標記為“可用”狀態(tài),使操作系統(tǒng)在分配內存時可以將它重新分配給其他變量使用。
那么,當指針變量被釋放后,它所指向的內存空間中的數(shù)據(jù)會怎樣呢?free 的標準行為只是表示這塊內存可以被再分配,至于它里面的數(shù)據(jù)是否被清空并沒有強制要求。不同的編譯器處理的方式可能不一樣。我們就看一下 VC++6.0 這個編譯器是怎么處理的:
可見在 VC++6.0 中,當指針變量被釋放后,雖然它仍然是指向那個內存空間的,但那個內存空間中的值將會被重新置一個非常小的負數(shù)。動態(tài)創(chuàng)建的內存如果不用了必須要釋放。注意,一個動態(tài)內存只能釋放一次。如果釋放多次程序就會崩潰,因為已經(jīng)釋放了,不能再釋放第二次。
綜上所述,malloc 和 free 一定要成對存在,一一對應。有 malloc 就一定要有 free,有幾個 malloc 就要有幾個 free,與此同時,每釋放一個指向動態(tài)內存的指針變量后要立刻把它指向 NULL。
注意事項
1)釋放一塊內存的一部分是不允許的。動態(tài)分配的內存必須整塊一起釋放。但是,realloc函數(shù)可以縮小一塊動態(tài)分配的內存,有效地釋放它尾部的部分內存。
2)不要訪問已經(jīng)被free函數(shù)釋放了的內存。假定對一個指向動態(tài)分配的內存的指針進行了復制,而且這個指針的幾份拷貝分散于程序各處。你無法保證當你使用其中一個指針時它所指向的內存是不是已被另一個指針釋放。還要確保程序中所有使用這塊內存的地方在這塊內存釋放之前停止對它的使用。
3)當動態(tài)分配的內存不再需要使用時,應該被釋放,這樣可以被重新分配使用。分配內存但在使用完畢后不釋放將引起內存泄漏(memory leak)。
點擊關注,第一時間了解華為云新鮮技術~華為云博客_大數(shù)據(jù)博客_AI博客_云計算博客_開發(fā)者中心-華為云
1.《C語言中動態(tài)內存是如何分配的?》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡信息知識,僅代表作者本人觀點,與本網(wǎng)站無關,侵刪請聯(lián)系頁腳下方聯(lián)系方式。
2.《C語言中動態(tài)內存是如何分配的?》僅供讀者參考,本網(wǎng)站未對該內容進行證實,對其原創(chuàng)性、真實性、完整性、及時性不作任何保證。
3.文章轉載時請保留本站內容來源地址,http://f99ss.com/gl/2177336.html