malloc,calloc和realloc的应用

先看这样一行代码

#include<stdio.h>

int main()
{
     
	char str[1024*1024];
	printf("hello");
	return 0;
}

此时程序崩溃,没有任何输出。
因为windows中栈的默认大小是1M,当执行main函数时,会先有一个保护现场而一些地址入栈,还有一系列操作占用栈空间,而使栈的空间不够分配1M而溢出。
此时就可以从堆区动态请求一定大小的内存,并且用完之后还给堆。
C语言动态内存管理有四个函数:malloc,calloc,realloc和free都需要引用stdlib. h或malloc. h
malloc
申请格式:void *malloc(size_t size)
释放:viod free(void *str)
举例:

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

int main()
{
     
  int n=0;
  int i;
  scanf("%d",&n);
  int *str=(int *)malloc(sizeof(int)*n);
  if (str==NULL)  exit(1);
  for(i=0;i<n;i++)
  {
     
	  str[i]=i+10;
  }

  free(str);
  str==NULL;
  return 0;

}

在这里有几个注意的地方:

  1. 申请动态内存后,先判断指针str是否为空。
  2. 用完后必须释放堆内存,否则会出现内存泄露。
  3. 使用free函数后会出现一个空悬指针,free函数只能使申请的动态内存恢复可用状态,指针还会指向堆,对堆内申请的内存进行操作,这时候就要使指针变成NULL。
    calloc
    申请格式:void *calloc(size_t,size_t size)
    示例:
#include<stdio.h>
#include<stdlib.h>

int main()\
{
     
  int n=0;
  int i;
  scanf("%d",&n);
  int *str=(int *)calloc(n,sizeof(int));
  if (str==NULL)  exit(1);
  free(str);
  str==NULL;
  return 0;

}

通过calloc申请的动态内存地址的默认值都为零。注意事项和malloc基本一样。
需要注意的是 memset函数
memset可以对申请的内存做初始化,格式为void *memset(void *p,int c,int n)
malloc必须用其进行初始化。

realloc
格式为 void(void *prt,size_t size)
示例:

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

int main()
{
     
  int n=5,m=10;
  int i;
  scanf("%d",&n);
  int *str=(int *)malloc(sizeof(int)*n);
  if (str==NULL)  exit(EXIT_FAILURE);
  for(i=0;i<n;i++)
  {
     
	  str[i]=i+10;
  }
  str=(int *)realloc(str,sizeof(int)*m);
  if(str==NULL) exit(EXIT_FAILURE);
   for(i=0;i<m;i++)
  {
     
	  printf("%d",str[i]);
  }
  free(str);
  str==NULL;
  return 0;

}

如上的情况为后者分配的内存大于前者,又分为两种情况

  1. 后续未分配内存空间足够大,可以分配空间。
  2. 后续未分配内存空间不够大,不能分配空间,这时候先释放旧申请的内存块,再重新申请新的栈空间
    还有一种情况就是堆内存不足,扩展空间失败,realloc返回NULL
    处理代码如下:
#include<stdio.h>
#include<stdlib.h>

int main()
{
     
	int *p=NULL;
	int *ip=(int *)malloc(sizeof(int)*10);
	if (ip==NULL)  exit(EXIT_FAILURE);
	//处理程序
	ip=(int *)realloc(ip,sizeof(int)*1000);
	//realloc分配失败,返回NULL?
	if(NULL==ip)  exit(EXIT_FAILURE);
	//正确处理的办法
	p=(int *)realloc(ip,sizeof(int)*1000);
    if(p==NULL)
	{
     
		//扩展失败
		free(ip);
		exit(EXIT_FAILURE);
	}
	else
	{
     
		ip=p;
		//处理程序
	}
	free(ip);
	ip=NULL;
	return 0;

}

注意:不能随意移动申请的动态内存地址,否则使用free的时候容易崩溃。例如:


int main()
{
     
	int n=0;
	int *ip=(int *)malloc(sizeof(int)*n);
	if(ip==NULL) exit(1);
	ip++;
	free(ip);
	ip=NULL;
	return 0;
}

动态内存申请的时候再注意下内存碎片

你可能感兴趣的:(笔记)