最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

第 19 講:內(nèi)存分配

2021-09-26 23:28 作者:SunnieShine  | 我要投稿

前文我們已經(jīng)說了很多有關(guān) C 語言的語法了。今天我們來講一點不同的理論:堆內(nèi)存(Heap Memory)和棧內(nèi)存(Stack Memory)。


堆內(nèi)存和棧內(nèi)存的定義

堆內(nèi)存和棧內(nèi)存是兩個不同的存儲空間,由于名稱不同,所以它們各自的功能也不同。堆內(nèi)存專門用來管理我們程序使用的大量數(shù)據(jù)信息,當(dāng)程序員不用的時候,可以自己手動釋放掉(具體我們稍后再說)。不過前文我們都沒有用過堆內(nèi)存。

棧內(nèi)存指的是,當(dāng)一個函數(shù)在生成的時候,就會在棧內(nèi)存上分配指定的函數(shù)執(zhí)行信息,以及參數(shù)、變量信息。當(dāng)函數(shù)執(zhí)行完畢后,這些信息會跟著函數(shù)銷毀而自動銷毀。這些內(nèi)容是程序為我們直接完成的,無需我們手動去搞。舉個例子。

當(dāng)我們調(diào)用 f 函數(shù)時,系統(tǒng)就會為我們自動生成一個函數(shù)棧,分配其中需要用到的 x、z 變量的空間以可以存放它們,然后生成足夠的空間可以讓我們?nèi)?zhí)行這些內(nèi)容。

當(dāng)執(zhí)行完畢整個函數(shù)(調(diào)用返回語句 return z;)后,f 函數(shù)被銷毀,此時,f 函數(shù)棧使用的空間就會被立刻釋放掉,留給其它程序或下一次執(zhí)行某處的時候用,這樣就可以節(jié)約內(nèi)容使用。不然一直占用著,程序的使用內(nèi)存就會越來越大。

當(dāng) f 執(zhí)行完后,里面的變量的內(nèi)存就會一起被釋放,因為這些變量所處的內(nèi)存的地方,就在這個函數(shù)棧里。這就是棧內(nèi)存的方式。C 語言確實也默認所有在函數(shù)內(nèi)定義的默認類型變量都是這樣的生命周期。這些自動化處理的變量也就是前文提到過的 auto 類型變量。比如上文實例給出的 auto int z = 3 就是一個自動化處理的變量,而且一般我們都不寫這個 auto 關(guān)鍵字。


使用堆內(nèi)存

既然棧內(nèi)存這么不方便,那么可以自定義使用堆內(nèi)存嗎?是的,這也是我們接下來要提到的話題。C 語言為我們貼心地搞了一個堆內(nèi)存的體系,讓我們可以更加靈活處理很多復(fù)雜的內(nèi)存分配的機制,也可以同時去避免函數(shù)棧銷毀后同時銷毀變量本身的方式。

下面我們將開始嘗試使用堆內(nèi)存分配內(nèi)存空間,并手動釋放它們。不過我們需要介紹幾個常用函數(shù),它們在使用的時候都需要在前文 #include 指令處添加 #include <malloc.h> 頭文件導(dǎo)入指令。


malloc 函數(shù)

考慮如下代碼。

我們嘗試在堆內(nèi)存里分配了一個足夠存放 int 的空間,而這坨空間的地址就是 malloc 函數(shù)的返回值。請注意,malloc 函數(shù)是具有通用性的,所以它可以為任何其它類型進行分配內(nèi)存空間,所以此時我們需要把得到的地址強制轉(zhuǎn)換為 int * 類型后賦值給 p,于是 p 就指向了這塊內(nèi)存了。

然后我們嘗試去比較 p。如果 p 不為 NULL 則繼續(xù)往下執(zhí)行。這是因為 malloc 函數(shù)在分配內(nèi)存失敗時將會返回 NULL 值。當(dāng)它不為 NULL,就說明了變量被成功分配內(nèi)存。另外,由于 NULL(void *)0 等價,所以它實際上也是 0 的特殊寫法。所以 p != NULL 依然可以認為是在和 0 進行比較,所以可以省略 != 0 部分,即改寫為 p 即可:

free 函數(shù)

這個函數(shù)用于釋放掉用完的內(nèi)存。上文里如果我們已經(jīng)完成了使用 p 的操作,那么我們就可以直接釋放掉它了,所以我們把這個指針變量寫到 free 函數(shù)里當(dāng)參數(shù)就可以完成釋放了。


realloc 函數(shù)

可以從單詞上看出,realloc 就是 re-alloc。re- 前綴表示“反復(fù)”,“又”、“再一次”的意思,而 alloc 是 allocation,即分配的簡寫。所以這個函數(shù)的用法是將已經(jīng)分配過的內(nèi)存空間再一次重新分配一下,這一次可以更改內(nèi)存分配的大小。如果你對這塊內(nèi)存目前的大小不滿意,你可以調(diào)大這個內(nèi)存空間,當(dāng)然你也可以調(diào)小。它的寫法是這樣的:

寫法很簡單,第一個參數(shù)傳入需要擴容和縮容的內(nèi)存塊指針,第二個參數(shù)傳入的則是新的分配大小。在內(nèi)存里,realloc 會為我們自動往后擴容和縮容空間。當(dāng)擴容的時候,如果發(fā)現(xiàn)后續(xù)連續(xù)空間不能使用的時候,它就會自動把數(shù)據(jù)拷貝到可以連續(xù)分配到足夠內(nèi)存空間的某處上,然后把這些剛才拷貝后的備份放到相對對應(yīng)好的位置上,并返回新內(nèi)存塊的首地址。這里是 pn 得到的內(nèi)存塊重新分配后,再次賦值給 pn。

請注意,這種賦值格式是存在嚴重的內(nèi)存 bug 的:

C6308: 'realloc' might return null pointer: assigning null pointer to 'pn', which is passed as an argument to 'realloc', will cause the original memory block to be leaked.

這段話的意思是,如果你要使用 realloc 函數(shù),就最好不要使用同一個變量來接受分配的地址。realloc 是可能返回 NULL 的,如果你用同一個變量接收的話,就可能導(dǎo)致新得到的地址是 NULL,這樣你原本的內(nèi)存塊就找不到了,此時出現(xiàn)內(nèi)存泄漏的 bug。


第 19 講:內(nèi)存分配的評論 (共 條)

分享到微博請遵守國家法律
霍城县| 车致| 抚顺县| 叙永县| 怀来县| 阜宁县| 大兴区| 杭锦旗| 静乐县| 葫芦岛市| 嘉祥县| 平邑县| 成武县| 鹤峰县| 邓州市| 福鼎市| 叙永县| 五家渠市| 华宁县| 夏邑县| 福清市| 柳江县| 南昌市| 阳信县| 米林县| 上犹县| 东平县| 葫芦岛市| 平舆县| 虎林市| 五寨县| 定南县| 会同县| 蛟河市| 潞西市| 蓬莱市| 绥芬河市| 库伦旗| 秦皇岛市| 资中县| 江华|