动态内存管理
1.为什么存在动态内存管理?
因为通过普通创建变量的方式开辟空间,空间太死板了,空间开辟过大会造成浪费,空间开辟过小会导致溢出,固定的内存大小好像总是不够灵活。
C语言给了我们一种方法,可以根据我们的需求开辟空间,给我们C语言使用者更多的灵活性。
2.动态内存函数的介绍
我们可以把可以我们可以调用的内存区分为三种区域
栈区:用来存放局部变量、函数形式参数(会被销毁的一些量);
堆区:用来动态内存分配(堆区上空间的维护) ,使用堆区上的空间需要malloc calloc realloc free函数。
静态区:用来存放静态变量、全局变量。
2.0 malloc和free
#include <stdlib.h>
void* malloc(size_t size);
在内存的堆区上向内存申请一个大小为size个字节的连续空间,
如果开辟成功返回一个储存这个空间首地址的指针,类型是void*
如果开辟失败,则返回一个NULL指针,因此对malloc函数必须做返回的检测。
如果参数size为0,malloc的行为是标准未定义的,取决于编译器。
但是返回void*我们不能直接使用,因此还需要强制类型转换。
int* p=(int*)malloc(40);
if(p==NULL)
{
return -1
}
free(p);
p=NULL;
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(40);
if (p == NULL)
{
return -1;
}
for (int i = 0; i < 10; i++)
{
p[i] = i;
}
free(p);
p = NULL;
return 0;
}
2.1 calloc
malloc和calloc都是用来动态内存分配的。
malloc函数只负责开辟在堆区申请空间并且返回起始地址,不初始化内存空间。
calloc函数在堆区上申请空间,并且初始化为0,返回起始地址
void* calloc(size_t num,size_t size);
num表示需要开辟的元素个数,size表示每个元素的大小(单位字节)。
想初始化 用calloc 不想初始化 用malloc
2.2 realloc
void* realloc(void* pastp,size_t size);
传入需要调整大小的内存空间的首地址,传入需要调整成的大小
调整空间时会遇到两种情况
如果原空间后面的连续空间足够,就会把后面的空间也给p 返回源空间的首地址;
如果原空间后面的连续空间不够,就会再找一块空闲空间,足够大的空间,然后把原空间中的数据都粘过去,然后返回新空间的首地址。
realloc如果找不到对应内存空间大小,就会返回NULL。
p=realloc(p,20*sizeof(int));
2.4 返回描述错误的字符串的函数 strerror
char* strerror(int errnum);
参数:errnum错误号,通常是errno
返回值:返回一个指向错误字符串的指针,该错误字符串描述了错误errno 需要头文件<string.h> <errno.h>
实例:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
FILE *fp;
fp = fopen("file.txt","r");
if( fp == NULL )
{
printf("Error: %s\n", strerror(errno));
}
return(0);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
int* p=(int*)malloc(4000000000000000);
if(p==NULL)
{
printf("%s\n",strerror(errno));
return -1;
}
else
{
for(int i=0;i<100;i++)
{
p[i]=i;
printf("%d\t",p[i]);
}
}
free(p);
p=NULL;
return 0;
}
3.常见的动态内存错误
-
开辟空间失败直接解引用空指针导致的错误。
- 解决方法:if(p==NULL){return -1;}
-
对动态开辟空间的越界访问
-
对非动态开辟的内存用free。
-
使用free释放一块动态开辟内存的一部分
-
对同一块动态内存多次释放
-
动态开辟内存忘记释放(内存泄漏)
- 在堆区申请的空间,有两种回收的方式
- 1.主动free;
- 2.程序退出的时候,申请的空间也会回收(如果我们运行的程序一直运行呢?比如服务器程序,空间不释放,开辟了空间用完了不还回去,导致内存逐渐不够了,这种情况我们叫做内存泄漏)
|