系列文章目录
动态内存函数的使用
文章目录
- malloc
- realloc
- calloc
- free
- 总结
一、为什么存在动态内存分配?
在学习C语言后,我们知道内存开辟的方式。
int a = 10;//在栈上开辟4个字节的空间
int arr[5] = { 0 };//在栈空间上开辟20个字节的连续空间
但是开辟的方式有两个特点:
1.空间开辟的大小是固定不变的。
2.开辟的数组必须指定数组的长度,才能在需要的时候分配。
但是对于我们在运行程序的时候才知道需要多少内存的时候显然不能满足开辟方式,这时候就需要动态内存开辟了。
二、动态内存函数的介绍
1.malloc和calloc
C语言提供动态内存开辟函数
malloc
void* malloc (size_t size);
如果开辟成功,就会返回一个指向开辟好空间的地址.
如果开辟失败,就会返回NULL指针,所以使用malloc返回值一定要检查.
返回值的类型是void* (指的是泛型),malloc不知道开辟的类型,根据需要来进行开辟。
注意如果size为0,是标准未定义的,取决于编译器。
calloc
void* calloc (size_t num, size_t size);
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
与malloc不同的是,calloc会在返回地址之前把申请的空间的每个字节初始化为全0。
2.realloc和free
realloc函数的出现让动态内存管理更加灵活。申请的空间可大可小。
str是要调整的内存地址 size 调整之后新大小 返回值为调整之后的内存起始位置。这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
void* realloc(void* str, size_t size);
free函数是专门对动态内存进行释放和回收的
原型如下:
如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
如果参数 ptr 是NULL指针,则函数不会执行。
void free(void* ptr);
三、常见的动态内存操作错误
1.如果p = NULL,就不能继续操作
int main()
{
int* p = (int)malloc(40);
*p = 30;//如果p的值是NULL就会出问题
free(p);
return 0;
}
2.动态内存开辟的越界访问
#include <stdlib.h>
int main()
{
int i = 0;
int* p = (int*)malloc(5 * sizeof(int));
if (p == NULL)
{
printf("%s", strerror(errno));//这里是打印错误信息
}
for (i = 0; i <= 6; i++)
{
*(p + i) = i;//当i = 5时就越界访问了
}
return 0;
}
3.对非动态内存开辟的内存free释放
int main()
{
int k = 20;
int* p = &k;
free(p);//这样是不行的,因为p的内存不是动态内存函数开辟的,不能由free释放
return 0;
}
4.只释放动态内存的一部分
int main()
{
int* str = (int*)malloc(40);
str + 5;
free(str);//此时的str指针不在指向原来的起始地址
return 0;
}
5.对同一块内存的多次释放
int main()
{
int* str = (int*)malloc(40);
free(str);
free(str);
return 0;
}
6.忘记释放动态内存开辟的空间,会造成内存泄漏
void test()
{
int* str = (int*)malloc(40);
if (str != NULL)
{
*str = 30;
}
}
int main()
{
test();
while (1);
return 0;
}
总结
使用动态内存函数记得引相应的头文件,不是动态内存开辟的,不能使用free释放,使用动态内存开辟记得末尾释放。
目录