內(nèi)存是程序運(yùn)行的基礎(chǔ)。所有正在運(yùn)行的代碼都保存在內(nèi)存里面。內(nèi)存需要處理各種各樣的數(shù)據(jù),包括鍵盤(pán)的數(shù)據(jù)、鼠標(biāo)的數(shù)據(jù)、usb的數(shù)據(jù)、串口的數(shù)據(jù)、攝像頭的數(shù)據(jù),那么這些數(shù)據(jù)經(jīng)過(guò)程序的處理之后,就要進(jìn)行輸出到串口、屏幕、usb等。
內(nèi)存只有一個(gè),但是程序里面的空間有很多種。但是內(nèi)存中的數(shù)據(jù)類(lèi)型只有幾種,比如說(shuō)全局中的數(shù)據(jù)、堆中的數(shù)據(jù)、臨時(shí)堆棧中的數(shù)據(jù)。那么他們有什么區(qū)別呢?我們可以通過(guò)代碼發(fā)現(xiàn)一些問(wèn)題。
(1)全局?jǐn)?shù)據(jù)
static int value = 100;
void process()
{
static int number = 10;
}
大家可以在這里看到,value和number的數(shù)據(jù)其實(shí)都屬于全局?jǐn)?shù)據(jù),這里的變量是不隨著函數(shù)的調(diào)用發(fā)生變化的。
(2)堆數(shù)據(jù)
void process()
{
char* point = (char*)malloc(100);
free(point);
}
這里的point分配的數(shù)據(jù)就是堆數(shù)據(jù),如果沒(méi)有free操作,那么它的存在也是全局的。只要內(nèi)存不主動(dòng)釋放,那么這個(gè)內(nèi)存就會(huì)以一直存在。
(3)臨時(shí)數(shù)據(jù)
void process()
{
char name[100] = {0};
return;
}
這里的數(shù)據(jù)都是堆棧內(nèi)部的數(shù)據(jù),一旦process調(diào)用結(jié)束返回之前,那么name地址指向的內(nèi)存空間已經(jīng)被其他函數(shù)使用。此時(shí)這段內(nèi)存空間對(duì)我們來(lái)說(shuō)已經(jīng)沒(méi)有什么意義了。所以,不管在函數(shù)里面用了多少空間,如果你想在函數(shù)返回之前繼續(xù)使用里面的數(shù)據(jù),務(wù)必在函數(shù)返回前拷貝完畢。
這篇博客的內(nèi)容比較簡(jiǎn)單,主要講述了內(nèi)存的一些內(nèi)容。其實(shí)關(guān)于內(nèi)存的東西還很多。這里說(shuō)明一下只是讓大家有一個(gè)了解:
1) 全局?jǐn)?shù)據(jù)是我們喜歡使用的類(lèi)型,用起來(lái)比較方便
2)堆數(shù)據(jù)是系統(tǒng)給我們安排的空間
3)堆??臻g只能存在于當(dāng)時(shí)的函數(shù)之中,函數(shù)返回即失去意義
雖然我們上面這么說(shuō),但是這三個(gè)概念有的時(shí)候也是可以相互遷移的,比如說(shuō):
1) 有的時(shí)候,我們?yōu)榱藴y(cè)試的需要,首先構(gòu)建一個(gè)全局內(nèi)存池,以后測(cè)試的內(nèi)存都是通過(guò)自定義的malloc在內(nèi)存池中分配的,所以這個(gè)時(shí)候,堆分配和全局聯(lián)系在了一起。
全局內(nèi)存空間 < =========> 內(nèi)存池 < =========> 本地空間分配
2) 如果我們使用的函數(shù)空間比較小,那么所有的操作就可以在一個(gè)函數(shù)內(nèi)部完成了,那么這時(shí)候全局空間和臨時(shí)堆棧是不是一致的呢
全局空間 < =============> 本地堆棧
上面的說(shuō)法有些繞,但是我們的目的只是想讓大家時(shí)刻明白:
a)必須時(shí)刻明白我們的數(shù)據(jù)在哪塊空間里面
b)內(nèi)存會(huì)不會(huì)越界
c)內(nèi)存會(huì)不會(huì)泄露
d)內(nèi)存訪問(wèn)的數(shù)據(jù)是否依然有效