C 语言动态内存管理malloc 函数calloc函数realloc函数,free函数

C语言提供的动态内存开辟的函数

文章目录

  • C语言提供的动态内存开辟的函数
  • 前言
  • 一、malloc函数
  • 二、calloc函数
  • 使用
  • 三, realloc函数
    • 注意事项
  • 四.free函数
    • 注意
    • 使用free的注意事项
      • 对NULL指针解引用操作
      • 对动态开辟的内存的越界访问
      • 对非动态内存开辟的空间进行free
      • 使用free释放动态开辟内存的一部分
      • 对同一块动态内存的多次释放
      • 动态开辟内存忘记释放(内存泄漏)


前言

1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数名,局部变量的名等。其操作方式类似于数据结构中的栈。
2、堆区(heap)— 由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。动态内存开辟
3、静态区(static)—全局变量和局部静态变量的存储是放在一块的。程序结束后由系统释放。
4、文字常量区—常量字符串就是放在这里的,程序结束后由系统释放


提示:以下是本篇文章正文内容,下面案例可供参考

一、malloc函数

void* malloc(size_ t size);函数名(字节大小)
这个函数向内存申请 - 块连续可用的空间, 并返回指向这块空间的指针。
●如果开辟成功, 则返回 - 一个指向开辟好空间的指针。//返回这块空间的起始位置的地址
●如果开辟失败, 则返回 - 个NULL指针, 因此malloc的返回值一定要做检查。
●返回值的类型是void*, 所以malloc函数并不知道开辟空间的类型, 具体在使用的时候使用者自己来决定。
●如果参数size为0, malloc的行为是标准是未定义的, 取决于编译器。
使用方法,函数名(字节大小)


二、calloc函数

语言还提供了一个函数叫calloc, calloc 函数也用来动态内存分配。原型如下 :
void* ca1lloc(size.t num, size _t size);
●函数的功能是为num个大小为size的元素开辟 - 块空间, 并且把空间的每个字节初始化为0。
●与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全0。
使用方法,函数名(元素个数,每个元素的长度)

使用

 int*p= (int*)malloc(10 * sizeof(int));//返回申请到空间的起始位置的地址
 //calloc函数 int*p= (int*)calloc(10,sizeof(int));
  
   if (p == NULL)
   {
       
           //打印错误原因的一个方式
           printf("%s\n", strerror(errno));
   }
   else
   {
       printf("申请成功");
       //正常使用空间

       //开始使用
       int i = 0;
       for (i = 0;i < 10;i++)
       {

           *(p + i) = i;
       }
       for (i = 0;i < 10;i++) {
           printf("%d ", *(p + i));

       }
   }

三, realloc函数

void* realloc(void* ptr, size._t size);

ptr是要调整的内存地址
size调整之后新大小
●返回值为调整之后的内存起始位置。
●这个函数调整原内存空间大小的基础.上, 还会将原来内存中的数据移动到新的空间。
使用方法 。函数名字(内存地址,调整之后新大小)

int* p = calloc(5, sizeof(int));*///并且把空间的每个字节初始化为0
 //假设这里,20个字节不能满足我们的使用了
//希望我们能够有40个字节的空间
//这里就可以使用realloc来调整动态开辟的内存
   int*p2= realloc(p, 40);// 接受新开辟的内存块的地址 

注意事项

如果直接是拿原地址接受新地址块int* p = realloc(p, 40)以下注意事项

1.如果p指向的空间之后有足够的内存空间可以追加,则直接追加,后返回p
2.如果p指向的空间之后没有足够的内存空间可以追加,则realloc函数会重新找一 个新的内存区域
一次性开辟好新的地址满足需求的空间,并且把原来内存中的数据拷贝回来,释放旧的内存空间
如果开辟空间失败就会导致原地址丢失

int*ptr= realloc(p, 40);//所以得用一个新的变量来接受函数的返回值
if (ptr != NULL)/{
    p = ptr;//将原有数据和新空间大小重新给p
}

四.free函数

原则谁开辟谁释放
void free(void* ptr); //函数名字(要释放的空间(指针))
free函数用来释放动态开辟的内存。
不是动态开辟的不需要free
●如果参数ptr指向的空间不是动态开辟的, 那free函数的行为是未定义的。
●如果参数ptr是NULL指针, 则函数什么事都不做
free( p);

注意

这里释放完后面内存是还给了系统但是p依旧存的还是那块已经不存在的地址
此时的p就成了野指针
解决
p = NULL;至空

使用free的注意事项

对NULL指针解引用操作

int *p = malloc(40); 
//p进行相关的判断
*p = 10;//malloc开辟空间失败-对NULL指针解引用

对动态开辟的内存的越界访问

int* p = (int*)malloc(40);//10个int
if (p == NULL)
{
	return 0;
}
int1 = 0;
//越界
for (i = 0;i <= 10; 1++){

* (p + i) = i; }//第11个元素

对非动态内存开辟的空间进行free

对非动态内存开辟的空间进行free
int a = 10;这个开辟是栈上的空间
int* p = &a;
*p = 20;
这个是非动态开辟空间释放是有问题的
free(p);
P = NULL;

使用free释放动态开辟内存的一部分

----free释放的指针只能是开辟好空间的起始位置开始释放

		int *p= (int*)malloc(40);
	if (p == NULL) 
	{
		return 0;
	}
	int i = 0;
	for (i = 0;i < 10;i++)
	{
		*p++ = i;//此时的指针已经指向最后一个元素后面,* (p + i) = i
	最好使用起始地址加下标的方式
	}


	//回收空间
	free(p);//此时free释放*p指向后面的空间
	p = NULL;
	return 0;

对同一块动态内存的多次释放

int* p = (int*)malloc(40);
	if (p == NULL)
	{
		return 0;
	}
	//使用
	//释放
	free(p);
	p == NULL;//如果没有这个操作就对多次释放了
	//....
	free(p);

动态开辟内存忘记释放(内存泄漏)

—一直吃电脑处理内存

while (1){
		malloc(1);
	}

你可能感兴趣的:(c语言,c++,c++)