先看这样一行代码
#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;
}
在这里有几个注意的地方:
- 申请动态内存后,先判断指针str是否为空。
- 用完后必须释放堆内存,否则会出现内存泄露。
- 使用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;
}
如上的情况为后者分配的内存大于前者,又分为两种情况
- 后续未分配内存空间足够大,可以分配空间。
- 后续未分配内存空间不够大,不能分配空间,这时候先释放旧申请的内存块,再重新申请新的栈空间
还有一种情况就是堆内存不足,扩展空间失败,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;
}
动态内存申请的时候再注意下内存碎片