malloc()函数用来在堆中申请内存空间,free()函数释放原先申请的内存空间。Malloc()函数是在内存的动态存储区中分配一个长度为size字节的连续空间。其参数是一个无符号整型数,返回一个指向所分配的连续存储域的起始地址的指针。当函数未能成功分配存储空间时(如内存不足)则返回一个NULL指针。
由于内存区域总是有限的,不能无限制地分配下去,而且程序应尽量节省资源,所以当分配的内存区域不用时,则要释放它,以便其他的变量或程序使用。
这两个函数的库头文件为:
#include<stdlib.h>
函数定义如下:
void *malloc(size_t size) //返回类型为空指针类型
void free(void *ptr)
例如:
int *p1,*p2;
p1=(int *)malloc(10*sizeof(int));
p2=p1;
……
free(p2) ; /*或者free(p1)*/
p1=NULL; /*或者p2=NULL */
malloc()函数返回值赋给p1,又把p1的值赋给p2,所以此时p1,p2都可作为free函数的参数。使用free()函数时,需要特别注意下面几点:
(1)调用free()释放指针所指向的内存后,不能再去访问被释放的内存空间。内存被释放后,很有可能该指针仍然指向该内存单元,但这块内存已经不再属于原来的应用程序,此时的指针为悬挂指针(可以赋值为NULL),也称野指针,该区域的数据可能没有变,我们成为脏数据。
(2)不能两次释放相同的指针。因为释放内存空间后,该空间就交给了内存分配子程序,再次释放内存空间会导致错误。也不能用free来释放非malloc()、calloc()和realloc()函数创建的指针空间,在编程时,也不要将指针进行自加操作,使其指向动态分配的内存空间中间的某个位置,然后直接释放,这样也有可能引起错误。
(3)在进行C语言程序开发中,malloc/free是配套使用的,即不需要的内存空间都需要释放回收。
下面是使用这两个函数的一个例子。
[root@localhost yangzongde]# cat malloc_example.c
#include<stdio.h> //printf() //(1)头文件信息
#include<stdlib.h> //malloc() //(2)
int main(void) //(3)
{
int count;
int* array;
if((array=(int *)malloc(10*sizeof(int)))==NULL) //(重点)(4)分配空间 10*4(int)个连续的空间
{
printf("malloc memory unsuccessful");
exit(1);
}
for (count=0;count<10;count++) //(5) 赋值
{
*array=count;
array++; //这就是为啥要为指针添加类型了
}
for(count=9;count>=0;count--) //(6)赋值
{
array--;
printf("%4d",*array);
}
printf("\n");
free(array); //(7)释放空间
array=NULL; //(8)将指针置为空,避免不安全访问
exit (0);
}
[root@localhost yangzongde]# gcc -o malloc_example malloc_example.c //编译
[root@localhost yangzongde]# ./malloc_example //运行
9 8 7 6 5 4 3 2 1 0
在以上程序中,(1)句中包含stdio.h头文件,从而在后面可以调用printf()函数。(2)句中包含stdlib.h头文件,其是malloc()函数的头文件。(3)句为函数的入口位置,此处采用Linux下编程标准,返回值为int型,argc为参数个数, argv[]为参数,envp[]存放的是所有环境变量。(4)句动态分配了10个整型存储区域,此语句可以分为以下几步。
① 分配10个整型的连续存储空间,并返回一个指向其起始地址的整型指针。
② 把此整型指针地址赋给array。
③ 检测返回值是否为NULL。
(5)、(6)句为数组赋值并打印输出,以免内存泄漏。(7)句调用free()函数释放内存空间。(8)句将一个NULL指针传递给array,虽然在很多情况下可以不用此句,但这样处理可以避免此指针成为野指针。
在C++中,使用new和delete运算符来实现内存的分配和释放,使用new/delete运算符实现内存管理比使用malloc/free函数更有优越性。new/delete运算符定义如下:
static void* operator new(size_t sz); //new运算符
static void operator delete(void* p); //delete运算符
下面是一段C++程序代码:
void UseNewDelete(void)
{
Obj *a = new Obj; //申请动态内存并且初始化
//…
delete a; //清除并且释放内存
}
下面详细介绍C++中new/delete运算符的使用方法。
class A
{
public:
A() { cout<<"A is here!"<~A() { cout<<"A is dead!"<private:
int i;
};
A* pA=new A; //调用new运算符申请空间
delete pA; //删除pA
其中,语句new A完成了以下两个功能:
(1)调用运算符new,在自由存储区分配一个sizeof(A)大小的内存空间。
(2)调用构造函数A(),在这块内存空间上初始化对象。
当然,delete pA完成相反的两件事:
(1)调用析构函数~A(),销毁对象。
(2)调用运算符delete,释放内存。
由此可以看出,运算符new和delete提供了动态分配和释放存储区的功能。它们的作用相当于C语言的malloc()和free()函数,但是性能更为优越。使用new比使用malloc()有以下几个优点:
(1)new自动计算要分配给对象的内存空间大小,不使用sizeof运算符,简单,而且可以避免错误。
(2)自动地返回正确的指针类型,不用进行强制类型转换。
(3)用构造函数给分配的对象进行初始化。
但是,使用malloc函数和new分配内存的时候,本身并没有对这块内存空间做清零等任何动作。因此,申请内存空间后,其返回的新分配的内存是没有零填充的,程序员需要使用memset()函数来初始化内存。