什么是动态内存?
void fun()
{
char strb[1024 * 1024] = {0};
}
int main()
{
char stra[1024 * 10] = {0};
fun();
return 0;
}
运行时程序崩溃,这是为什么呢?
分析编译链接过程,我们知道栈区在函数被调用时分配,用来存放函数的参数值,局部变量等。在window中栈的默认大小时:1M,在visual studio中我们可以设置栈区的大小,在Linux中栈的默认大小为10M,在gcc编译时可以设置栈区的大小。
堆区:程序运行时可以在堆区动态的请求一定大小的内存,并在用完之后归还给堆区,在Linux系统中堆区的大小一般接近3G。
因此当我们需要大块内存或程序在运行过程中才知道所需内存的大小,我们就从堆区分配空间。
动态内存分配函数
malloc
向堆区申请一块指定大小的连续内存空间
void* malloc(size_t size);
typedef unsigned int size_t;
size: 要分配的字节数
分配成功:返回指向新分配内存的指针,为避免内存泄漏,必须要用free()释放分配的空间。
失败:返回空指针
void free(void* ptr);
int main()
{
int n = 0;
int i = 0;
int *ip = NULL;
scanf("%d",&n);
ip = (int*)malloc(sizeof(int)*n);
if(NULL == ip) exit(1);
for(int i = 0;i < n;i++)
{
ip[i] = i + 10;
}
free(ip);//空悬指针
ip = NULL;
return 0;
}
free之后一定要将指针置空,因为当我们把指针指向的堆空间释放之后,指针就变成失效指针,依旧指向哪里,当我们重新申请堆区空间,进行使用的时候,旧指针会影响新申请的堆空间。
对同一个空间只能释放一次
calloc
分配并使用零初始化连续内存空间
void* calloc(size_t num,size_t size)
num : 元素数目
size:每个对象元素的大小
分配成功:返回指向新分配内存的指针。
失败:返回空指针
int main()
{
int n = 0;
int *ip = NULL;
scanf("%d",&n);
ip = (int*)calloc(n,size(int));
if(NULL == ip) exit(1);
free(ip);//空悬指针
ip = NULL;
return 0;
}
自实现calloc函数。
void my_calloc(size_t num,size_t size)
{
void* vp = malloc(num * size);
if(NULL != vp)
{
memset(vp,0,num * size);
}
return vp;
}
realloc
我们使用malloc或calloc申请了堆空间内存,但是在程序运行的过程中发现空间申请少了或者多了如何处理?
realloc:扩充之前分配的内存块
void *realloc(void *ptr,size_t new_size);
ptr:指向需要重新分配的内存区域的指针
new_size:数组的新大小
realloc函数调整内存大小分为三种情况:
1、后续未分配内存空间足够大,可以分配空间
2、后续未分配内存空间不足够大,不能分配空间
3、堆内存不足,扩展空间失败,realloc函数返回空。
free
int main()
{
int n = 10;
int *ip = (int*)malloc(sizeof(int) * n);
if(NULL == ip) exit(1);
for(int i = 0;i < n;i++)
{
ip[i] = i;
}
ip += 5;
free(ip);
return 0;
}
当我们用malloc申请了多少个字节,就要用free释放多少个字节,当用malloc申请空间时,我们会和free达成一个协议,申请空间时,会有一个头部信息,它会记录申请空间的字节个数,free就会按申请的字节个数进行释放。