C语言:动态内存管理方式(malloc,calloc,realloc,free)

版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/qq_42719751/article/details/89295186

为什么要进行动态内存管理?

普通的内存开辟方式有下面两种:

	int val = 1;//在栈空间上开辟4个字节的空间
	char array[10] = {0};//在栈空间上开辟10个字节的空间

但是,上面开辟空间的方式有缺陷:

  1. 开辟出来的空间大小是固定的;
  2. 数组在声明时,必须指定数组的长度,它所需要的内存在编译时分配;

所以,如果我想要灵活的申请空间,上面的方法显然不能满足,这是就需要利用动态内存开辟的方式来申请空间了。

进行动态内存管理的几个函数

开辟空间的函数

1.malloc()函数

函数原型:

void* malloc ( size_t size );

malloc函数的作用就是在堆上申请一块连续可用的空间,并返回指向这片空间地址的指针。
在使用malloc函数时需要注意的地方:

  • 如果开辟成功,则返回一个指向开辟好空间的指针。
  • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
  • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
  • 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。

2.calloc()函数
函数原型:

void* calloc ( size_t num, size_t size );
  • num:要分配的元素个数;
  • size:每个元素的大小;

calloc函数的功能与malloc函数的功能相同,都是用来在堆上申请空间的。不同的地方是:

calloc函数申请出来的空间会初始化为0 ;

除此之外,和malloc一样。

3.realloc()函数
函数原型:

void* realloc ( void * ptr, size_t size );
  • ptr是要调整的内存的地址;
  • size是调整之后内存的大小;
  • 返回值为调整之后的内存的起始空间位置;

realloc函数的也是用来在堆上申请空间的,但是realloc函数使动态内存管理更加的灵活。
realloc函数可以在已经申请好的内存空间上在追加内存空间。

在realloc函数申请内存空间时有两种情况:

  1. 原有空间后有足够大的空间;
    此时直接在原空间的后边追加空间,返回原有空间的首地址;
  2. 原有空间后的空间不够所要追加的空间大小;
    在对空间上重新找一块大小合适的连续空间,将原空间的内容拷贝一份,保存到这块大小合适的连续空间中,返回这块大小合适的空间的首地址;
    在这里插入图片描述

上面三个申请空间的函数有个必须要注意的地方:

  • 使用时,返回值要强转;
  • 使用这三个函数时,要包含stdlib,h头文件;

释放内存空间的函数

4.free()函数
函数原型:

void* free ( void* ptr ) ;

free函数的作用是:释放由malloc函数,calloc函数,realloc函数动态开辟的内存空间
需要注意:
动态申请的内存空间,必须释放,如果不释放,会产生内存泄漏

常见的动态内存错误

  • 对空指针的解引用;
void test()
{
 	int *p = (int *)malloc(INT_MAX/4);
 	*p = 20;//如果p的值是NULL,就会有问题
 	free(p);
}
  • 对动态开辟空间的越界访问;
void test()
{
 	int i = 0;
	int *p = (int *)malloc(10*sizeof(int));
 	if(NULL == p)
 	{
 		exit(EXIT_FAILURE);
	 }
 	for(i=0; i<=10; i++)
 	{
 		*(p+i) = i;//当i是10的时候越界访问
	 }
 	free(p);
}
  • 对非动态开辟内存使用free释放;
void test()
{
	int a = 10;
 	int *p = &a;
	free(p);//ok?
}
  • 使用free函数释放动态开辟内存的一部分;
void test()
{
	int * p = (int*) malloc (100);
	p++;
	free(p);//p不再指向动态内存的起始位置
}
  • 对同一块动态内存多次释放;
void test()
{
	int *p = (int*) malloc(100);
	free(p);
	free(p);//重复释放
}
  • 动态开辟内存忘记释放(内存泄漏);
void test()
{
	int* p = (int*) malloc(100);
	if(NULL != p)
	{
		*p = 20;
	}
}
int main ()
{
	test():
	
	return 0;
}

keep Running

猜你喜欢

转载自blog.csdn.net/qq_42719751/article/details/89295186