1. 程式人生 > >記憶體管理之malloc、free、calloc和realloc

記憶體管理之malloc、free、calloc和realloc

記憶體區域可以分為棧,堆,靜態儲存區和常量儲存區。區域性變數,函式形參,臨時變數都是在棧上獲得記憶體的,它們獲取的方式都是由編譯器自動執行的。
C 標準函式庫提供了許多函式來實現對堆上記憶體管理,其中包括:malloc函式,free函式,calloc函式和realloc函式。使用這些函式需要包含標頭檔案stdlib.h

1.malloc函式

malloc函式可以從堆上獲得指定位元組的記憶體空間,其函式宣告如下:

void * malloc(int n);

其中,形參n為要求分配的位元組數。如果函式執行成功,malloc返回獲得記憶體空間的首地址;如果函式執行失敗,那麼返回值為NULL。由於malloc函式值的型別為void型指標,因此,可以將其值型別轉換後賦給任意型別指標,這樣就可以通過操作該型別指標來操作從堆上獲得的記憶體空間。

需要注意的是,malloc函式分配得到的記憶體空間是未初始化的。因此,一般在使用該記憶體空間時,要呼叫另一個函式memset來將其初始化為全0。memset函式的宣告如下:

    void * memset (void * p,int c,int n) ;

該函式可以將指定的記憶體空間按位元組單位置為指定的字元c。其中,p為要清零的記憶體空間的首地址,c為要設定的值,n為被操作的記憶體空間的位元組長度。如果要用memset清0,變數c實參要為0。

注意:通過malloc函式得到的堆記憶體必須使用memset函式來初始化。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	int * p = NULL;
	p = (int *) malloc(sizeof(int));

	if (NULL == p) {
		printf("Can't get memory!\n");
		return -1;
	}

	printf("%d\n", *p);           //輸出分配的空間上的值
	memset(p, 0, sizeof(int));     //將p指向的空間清0
	printf("%d\n", *p);           //輸出呼叫memset函式後的結果
	*p = 2;
	printf("%d\n", *p);

	return 0;
}


2. free函式



       從堆上獲得的記憶體空間在程式結束以後,系統不會將其自動釋放,需要程式設計師來自己管理。一個程式結束時,必須保證所有從堆上獲得的記憶體空間已被安全釋放,否則,會導致記憶體洩露。例如上面的demo就會發生記憶體洩露。

free函式可以實現釋放記憶體的功能。其函式宣告為:

void free (void * p);

由於形參為void指標,free函式可以接受任意型別的指標實參。
但是,free函式只是釋放指標指向的內容,而該指標仍然指向原來指向的地方,此時,指標為野指標,如果此時操作該指標會導致不可預期的錯誤。安全做法是:在使用free函式釋放指標指向的空間之後,將指標的值置為NULL。因此,對於上面的demo,需要在return

語句前加入以下兩行語句:

free(p);
p=NULL;


注意:使用malloc函式分配的堆空間在程式結束之前必須釋放。


3. calloc函式



calloc函式的功能與malloc函式的功能相似,都是從堆分配記憶體。其函式宣告如下:

void *calloc(int n,int size);

函式返回值為void型指標。如果執行成功,函式從堆上獲得size X n的位元組空間,並返回該空間的首地址。如果執行失敗,函式返回NULL。該函式與malloc函式的一個顯著不同時是,calloc函式得到的記憶體空間是經過初始化的,其內容全為0。calloc函式適合為陣列申請空間,可以將size設定為陣列元素的空間長度,將n設定為陣列的容量。


4. realloc函式


realloc函式的功能比malloc函式和calloc函式的功能更為豐富,可以實現記憶體分配和記憶體釋放的功能,其函式宣告如下:

void * realloc(void * p,int n);

其中,指標p必須為指向堆記憶體空間的指標,即由malloc函式、calloc函式或realloc函式分配空間的指標。realloc函式將指標p指向的記憶體塊的大小改變為n位元組。如果n小於或等於p之前指向的空間大小,那麼。保持原有狀態不變。如果n大於原來p之前指向的空間大小,那麼,系統將重新為p從堆上分配一塊大小為n的記憶體空間,同時,將原來指向空間的內容依次複製到新的記憶體空間上,p之前指向的空間被釋放。relloc函式分配的空間也是未初始化的。

注意:使用malloc函式,calloc函式和realloc函式分配的記憶體空間都要使用free函式或指標引數為NULL的realloc函式來釋放。
#include<stdio.h>
#include<stdlib.h>

int main() {
	int *p = NULL;
	p = (int *)malloc(sizeof(int));
	*p = 3;
	printf("p=%p\n", p);
	printf("*p=%d\n", *p);

	p = (int *)realloc(p, sizeof(int));
	printf("p=%p\n", p);
	printf("*p=%d\n", *p);

	p = (int *)realloc(p, sizeof(int)*3);
	printf("p=%p\n", p);
	printf("*p=%d\n", *p);

	//釋放p指向的空間
	realloc(p, 0);
	p = NULL;

	return 0;
}

執行結果:
p=00A42A88
*p=3
p=00A42A88
*p=3
p=00A40F00
*p=3


注意:如果要使用realloc函式分配的記憶體,必須使用memset函式對其記憶體初始化。

相關推薦

記憶體管理mallocfreecallocrealloc

記憶體區域可以分為棧,堆,靜態儲存區和常量儲存區。區域性變數,函式形參,臨時變數都是在棧上獲得記憶體的,它們獲取的方式都是由編譯器自動執行的。 C 標準函式庫提供了許多函式來實現對堆上記憶體管理,其中包括:malloc函式,free函式,calloc函式和realloc函式

Linux記憶體管理malloc實現

程序虛擬地址空間由一個一個VMA來表示,這裡先接收VMA相關操作. 1.1 查詢VMA函式find_vma() struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) 找到的vma結果需滿足條件:

Linux下程序記憶體管理mallocsbrk

之前自己突發興趣想寫一下malloc函式,順便了解一下程序的記憶體管理。在寫的過程中發現其實malloc只不過是通過呼叫Linux下的sbrk函式來實現記憶體的分配,只是在sbrk之上加了一層對所分配的記憶體的管理罷了,而sbrk以及brk是實現從虛擬記憶體到記憶體的對映的

C語言動態記憶體管理malloccallocreallocfree的用法注意事項

此文是參考http://www.cplusplus.com/reference/cstdlib/裡的動態記憶體管理部分所寫,如發現有問題和不足之處,請參看原文,最好能幫忙指出,謝謝。 1.void* malloc (size_t size); malloc:分配一塊size

C語言動態記憶體管理mallocrealloccalloc以及free函式

我們已經掌握的記憶體開闢方式有: int val = 20;//在棧空間上開闢四個位元組 char arr[10] = {0};//在棧空間上開闢10個位元組的連續空間 但是這種開闢空間的方式有兩個特點: 1. 空間開闢的大小是固定的。

動態記憶體分配(mallocfreecallocrealloc

1. void*   malloc(size_t size);     //size_t   size表示的是記憶體的總大小 a、malloc所分配的是一塊連續的記憶體,以位元組為單位,並且不帶任何資訊 b、malloc實際分配的記憶體可能比請求的稍微多一點(什麼原因呢?思

mallocfreerealloccalloc函數

C語言malloc函數 原型:extern void* malloc(unsigned int size); 功能:動態分配內存; 註意:size僅僅為申請內存字節大小,與申請內存塊中存儲的數據類型無關,故編程時需要通過以下方式給出:"長度 * sizeof(數據類型)"; 示例

Java記憶體管理類似-Xms-Xmx 這些引數的含義

Java記憶體管理之類似-Xms、-Xmx 這些引數的含義 答: 1.堆記憶體分配: JVM 初始分配的記憶體由**-Xms** 指定,預設是實體記憶體的 1/64; JVM 最大分配的記憶體由**-Xmx** 指定,預設是實體記憶體的 1/4; 預設空餘

Java記憶體管理用什麼方式回收垃圾管理記憶體呢?垃圾回收演算法有哪些?

文章目錄 1. 什麼是垃圾? 2. 標記-清理(Marked-Sweep) 3. 標記-整理(Marked-Compact) 4. 複製(Copying) 6. Java分代回收機制 6.1 新生代-複製 回收機制

NSString的記憶體管理 __NSCFConstantStringNSTaggedPointerString__NSCFString

by skyfly 在 Objective-C 的 Fondation 框架中 NSString 物件是很複雜的存在,各種方式建立以及不同長度的字串都會影響 NSString 物件在記憶體中所處的位置。Objective-C 在執行時也對其做了很多優化。今天就來研究

Java記憶體管理類似-Xms-Xm 這些引數的含義

Java記憶體管理之類似-Xms、-Xmx 這些引數的含義 答: 1.堆記憶體分配: JVM 初始分配的記憶體由**-Xms** 指定,預設是實體記憶體的 1/64; JVM 最大分配的記憶體由**-

存儲管理硬件基礎機械磁盤原理以及設備規範MBR格式的分區管理

linux存儲管理Linux系統管理 存儲管理(服務器數據處理速度大於日常PC及移動端設備,多顆cpu,CPU多核心,每個核心可以完成一個進程的處理) 傳統的機械磁盤及分區管理 RAID技術,軟RAID實現 LVM Btrfs 文件系統管理: ext、xfs、btrfsLinux存儲管理(數據存

Linux系統管理初步(二)iofreepsnetstat命令 編輯中

sha 系統 工具 可能 工作 ued uri per str 10.6 監控io性能10.7 free命令10.8 ps命令10.9 查看網絡狀態10.10 linux下抓包 一、iostat與iotop命令 iostat命令與iotop,命令能夠看出系統磁盤的工作情況,

Linux系統管理Python生態工具文本處理系統管理

相對 print 重復調用 示例 快捷 python編程 expr markup htm 一、Python生態工具 一、Python內置小工具   1、秒級啟動一個下載服務器   Python 內置了一個下載服務器就能夠顯著提升效率了 。 例如, 你的同事要讓你傳

記憶體管理中的程式碼段資料段,棧,堆

1.函式程式碼存放在程式碼段。宣告的類如果從未使用,則在編譯時,會優化掉,其成員函式不佔程式碼段空間。 全域性變數或靜態變數,放在資料段, 區域性變數放在棧中, 用new產生的物件放在堆中, 記憶體分為4段,棧區,堆區,程式碼區,全域性變數區 BSS段:BSS段(bss segment)

記憶體管理malloc free 用法)

一、malloc() 和 free() 的基本概念和基本用法 1. 函式原型及說明 void *malloc( long NumBytes) 該函式分配了NumBytes個位元組,並返回了指向這塊記憶體的指標。如果分配失敗,則返回一個空指標NULL。失敗的原因有很多

Bean管理配置(@PostConstruct@PreDestroy@Scope)

package com.imooc.demo2; import org.springframework.stereotype.Component; import javax.annotation.

C/C++中的malloccallocrealloc

1. malloc 原型:extern void *malloc(unsigned int num_bytes); 標頭檔案:Visual C++6.0中可以用malloc.h或者stdlib.h 功能:分配長度為num_bytes位元組的記憶體塊 返回值:如果分配成功則返回指向被分配記憶體的指標(此儲存區

記憶體管理mallocfree用法)

        在C語言的學習中,對記憶體管理這部分的知識掌握尤其重要!之前對C中的malloc()和free()兩個函式的瞭解甚少,只知道大概該怎麼用—— 就是malloc然後free就一切OK了。當然現在對這兩個函式的體會也不見得多,不過對於本文章第三部分的內容倒是有了

深入C#記憶體管理來分析 值型別引用型別裝箱拆箱堆疊幾個概念組合

-C#初學者經常被問的幾道辨析題,值型別與引用型別,裝箱與拆箱,堆疊,這幾個概念組合之間區別,看完此篇應該可以解惑。   俗話說,用思想程式設計的是文藝程式猿,用經驗程式設計的是普通程式猿,用複製貼上程式設計的是2B程式猿,開個玩笑^_^。   相信有過C#面試經歷的人,對