动态内存管理
动态内存分配
创建变量与自定义类型所开辟的空间大小都是固定的。
而数组声明的时候,必须指定数组的长度,在编译期间完成数组内存的分配。
为了在程序运行时开辟或减少内存空间,要用到动态内存函数。
动态内存函数介绍
计算机数据的 内存分为三个区域:
栈区存放局部变量,形式参数
堆区用于动态内存的开辟
静态区用于存放全局变量与静态变量
动态内存函数开辟空间失败时会返回null
malloc
开辟内存空间(按字节算),并返回申请空间的首地址, 用该首地址访问内存空间。申请到的内存空间在堆区,申请到的空间并没有初始化,放的是随机值。
void* malloc (size_t size);
int *p=(int *)malloc(40); \\开辟40字节的空间大小,并强制类型转换返回值为int* 类型的指针
malloc申请的内存空间当程序退出时才会还给操作系统,程序不退出不会主动释放申请到的内存空间,需要主动使用free函数释放空间。
int main()
{
int *p=(int *)malloc(40);
if(p==NULL)
{
perror("malloc"); \\判断是否成功申请到的内存空间
return 0;
}
free(p); \\主动释放p指向的内存空间
p=null; \\将p置空
}
free
void free (void* ptr);
如果参数指针指向的空间不是动态内存开辟的,free函数的行为未定义则出现错误
如果参数指针为null,则函数不进行动作
calloc
void* calloc (size_t num, size_t size);
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
realloc
在原有基础上对开辟的内存空间进行扩容或减小
void* realloc (void* ptr, size_t size);
ptr 是要调整的内存地址,size 调整之后新大小,返回值为调整之后的内存起始位置。
realloc在调整内存空间的是存在两种情况:
1:原内存空间后面有着足够空间开辟,则申请开辟后返回原来的首地址
2: 若原内存空间后面没有足够空间开辟,则会申请一片新的空间开辟足够的空间大小(连带原空间),并将原空间的内容复制到新空间内,将原空间释放。
int main()
{
int *ptr = (int*)malloc(100);
if(ptr = NULL)
{
perror("malloc"); \\判断是否成功申请到的内存空间
return 0;
}
int*p = NULL;
p = realloc(ptr, 1000); \\另外创建一个指针变量p,判断p不为null后赋值给ptr,避免原有的内存数据因为开辟失败而造成数据丢失
if(p != NULL)
{
ptr = p;
}
free(ptr);
return 0;
}
动态开辟内存的常见错误
对NULL指针的解引用操作
对动态开辟空间的越界访问
对非动态开辟内存使用free释放
使用free释放一块动态开辟内存的一部分:改变了原先的指向内存首地址的指针后在进行free释放,会出现err
对同一块动态内存多次释放
动态开辟内存忘记释放(内存泄漏):动态申请的内存空间不会出了作用域自动销毁,只有主动free销毁或者程序结束
void test()
{
int *p = (int *)malloc(100);
if(NULL != p)
{
*p = 20;
}
}
int main()
{
test();
while(1);
}
调用的函数内不进行内存的释放,出函数后,p指针作为临时变量销毁,而开辟的内存并未释放,造成内存占用不结束,若程序一直运行,占用的内存未释放便不能使用。