C語言動態分配記憶體

2021-08-20 19:45:25 字數 2966 閱讀 8660

動態開闢記憶體的函式:

void* malloc (size_t size);
這個函式向記憶體申請⼀塊連續可⽤的空間,並返回指向這塊空間的指標

如果開闢成功,則返回⼀個指向開闢好空間的指標

如果開闢失敗,則返回⼀個null指標,因此malloc的返回值⼀定要做檢查

返回值的型別是 void* ,所以malloc函式並不知道開闢空間的型別,具體在使⽤的時候使⽤者自己來決定

如果引數 size 為0, malloc的⾏為是標準是未定義的,取決於編譯器

calloc 函式也⽤來動態記憶體分配。函式原型如下:

void *calloc(size_t num, size_t size);
函式的功能是為 num 個⼤⼩為 size 的元素開闢⼀塊空間,並且把空間的每個位元組初始化為0。

與函式 malloc 的區別只在於 calloc 會在返回位址之前把申請的空間的每個位元組初始化為全0。

realloc函式的出現讓動態記憶體管理更加靈活。

有時我們會發現過去申請的空間不夠用或者用不完,那 realloc 函式就可以做到對動態開闢記憶體大小的調整。 函式原型如下:

void* realloc (void* ptr, size_t size);
ptr 是要調整的記憶體位址

size 調整之後新大小

返回值為調整之後的記憶體起始位置。

這個函式調整原記憶體空間大小的基礎上,還會將原來記憶體中的資料移動到新的空間。

realloc在調整記憶體空間的是存在兩種情況:

1. 原有空間之後有⾜夠⼤的空間

2. 原有空間之後沒有⾜夠⼤的空間

當是情況1 的時候,要擴充套件記憶體就直接原有記憶體之後直接追加空間,原來空間的資料不發生變化。

函式free,專門是⽤來做動態記憶體的釋放和**的,函式原型如下:

void

free (void* ptr);

如果引數 ptr 指向的空間不是動態開闢的,那free函式的行為是未定義的。

如果引數 ptr 是null指標,則函式什麼事都不做。

這裡我不禁產生了個疑問:既然會對已經開闢的記憶體進行realloc、free,那編譯器是怎麼知道開闢的這段記憶體有多大呢?

在vs2013中,我做了乙個測試:

int main()

在測試中,我們申請了4個位元組大小的空間。

單步除錯後,跳轉到malloc函式的定義處:

繼續f11加f10,可以在dbgheap.c檔案中看到這樣一句話:

blocksize =sizeof(_crtmemblockheader) + nsize + nnomanslandsize;
這裡的_crtmemblockheader是乙個結構體。它的大小是多少呢?轉到它的定義處發現:

typedef struct _crtmemblockheader

_crtmemblockheader;

可以看到,兩個struct _crtmemblockheader *佔了8個位元組,再加上char *int,就是16個位元組;然後無論是不是64位系統,都要加上intsize_t的8個位元組,就是24個位元組;然後再加上longunsigned char的5個位元組,總共有29個位元組。又因為結構體的對齊規則,所以整個_crtmemblockheader的大小就是32個位元組。

那其他兩個呢?

在dbgint.h的315行,會看到巨集nnomanslandsize的值#define nnomanslandsize 4

另乙個nsize的大小剛好為4,blocksize的大小就是32+4+4=40個位元組。

接著往下看,在圈起來的部分,可以看到系統用剛剛的blocksize大小到堆區去申請空間了。

現在意思就很明顯了:在主函式中我們申請了4個位元組大小的空間,而實際是在堆上多申請了32加4個位元組。那這多出來的位元組用來幹嘛了呢?繼續往下除錯**,可以看到:

系統往剛剛在堆中申請的空間做了初始化操作:往真正使用者需要的四個位元組中填充0xcd;往使用者需要空間的首尾以外的4個位元組,填充0xfd

最後,返回給p的就是那被填充0xcd的四個位元組:

至此,結果已經出來了:系統在動態分配記憶體時並不是真正使用者要多少就申請多少,而是會在每乙個使用者申請空間時多申請32+4個位元組的空間,用來標記和管理分配給使用者的空間。對於使用者而言,在不出意外的情況下,每次感覺「自己真正申請了n個位元組」,而實際上卻不是這樣。

既然每次動態地在堆上申請空間時,都會多申請32+4個位元組的空間。若是在做鍊錶時每次都只申請很少的位元組,那將會造成很大的空間浪費。所以用c語言的動態開闢空間時,因注意到這一點。

C語言動態分配記憶體知識

陣列的長度必須事先指定,只能是常整數,不能是變數 傳統形式定義的陣列,該陣列的記憶體程式設計師無法手動釋放,只能在定義 該陣列的函式使用完畢後,釋放陣列占用的記憶體。陣列的長度一旦定義,其長度就不能更改。傳統形式定義的陣列不能跨函式使用。動態記憶體分配可以很好的解決傳統陣列的缺點。傳統陣列也被稱之為...

C語言動態分配記憶體0823

動態分配記憶體 1為什麼 2c裡面怎麼動態分配記憶體 3c new delete 1因為陣列的範圍有限,如果陣列的太大,就要申請記憶體。2molloc 在c中 然而在c 中 new 中會執行建構函式。molloc 中是不會執行建構函式,列如 maclass p new maclass 執行建構函式 ...

C語言動態分配記憶體問題

動態分配記憶體和直接分配記憶體區別 1.直接分配記憶體,如int p 是分配在棧上的,可以對其初始化 2.動態分配記憶體,int p malloc 100 是分配在堆記憶體上的 free 釋放記憶體問題 free函式只能對動態分配的記憶體進行釋放,釋放後該指標仍保留位址,但是記憶體被釋放,成為野指標...