文章目录
前言
动态内存分配
提示:以下是本篇文章正文内容,下面案例可供参考
一、为什么要进行动态内存分配
对于静态内存
数组的长度必须事先指定,而且只能是常量,不能是变量,
如果一开始设定太大,存入数据可能后面的空间空很多,太小有可能导致存不下
而且对于数组所占内存空间程序员无法手动编程释放,只能在函数运行结束后由系统自动释放
那可不可以让内存空间随我的需要而变大变小,抑或想释放就释放呢?
这就要进行动态内存分配
对于动态内存分配
更灵活,随时手动释放空间
二、如何进行动态内存分配
四个函数
开辟空间 - 堆区
- malloc
- realloc
- calloc
回收空间
- free
头文件均为 #include <stdilb.h>
在堆区开辟空间
malloc
// malloc
//库函数形式: void *malloc( size_t size );
//()内为想要开辟的空间总字节大小
// 失败返回NULL,成功返回开辟空间的首地址
#include <stdlib.h>
int main(void)
{
//开辟10个整型的空间在堆区
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
perror("main");
return 0;
}
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
printf("%d", *(p + i));
}
free(p);
//归还堆区上的空间
p = NULL;
//主动设置p为NULL
return 0;
}
开辟失败:
calloc
代码如下(示例):
// calloc
//void* calloc(size_t num, size_t size);
//与malloc不同的一点:calloc会将开辟的内存初始化为0
int main(void)
{
int* p = calloc(10, sizeof(int));
if (p == NULL)
{
return 1;
}
free(p);
p = NULL;
return 0;
}
特别:开辟空间的同时将开辟的内存初始化为0
realloc
// realloc - 可以将内存进行灵活调整
//void* realloc(void* memblock, size_t size);
int main(void)
{
int* p = (int*)calloc(10,sizeof(int));
if (p == NULL)
{
perror("main");
return 0;
}
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
printf("%d", *(p + i));
}
//调整空间大小为20
int* tmp = realloc(p, 20 * sizeof(int));
if (tmp != NULL)
{
p = tmp;
}
free(p);
//归还堆区上的空间
p = NULL;
//主动设置p为NULL
return 0;
}
最为关键的一个函数:可以灵活调整内存
回收空间 - free
回收堆区的空间
void free( void *memblock );
错误示范
int main()
{
//错误
int arr[10];//在栈区上开辟的空间
int* p = arr;
free(p);
return 0;
}
正确形式上文都有涉及
当free参数为NULL时,无空间释放
常见动态内存分配问题
常见动态内存的错误
1.对NULL指针解引用
int main(void)
{
int* p = (int*)malloc(10000000000000000);
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
return 0;
}
2.越界访问
int main(void)
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
return 1;
}
int i = 0;
for (i = 0; i <= 40; i++)
{
*(p+i) = i;
}
return 0;
}
3.用free释放非动态开辟的空间
int main(void)
{
int arr[10] = { 0 };
int* p = arr;
free(p);
p = NULL;
return 0;
}
4.使用free释放动态内存中的一部分
int main(void)
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
return 1;
}
int i = 0;
for (i = 0; i < 5; i++)
{
*p++ = i;
}
//此时p不在指向起始位置了
free(p);
p = NULL;
return 0;
}
5.多次释放同一动态内存空间
int main(void)
{
int* p = (int*)malloc(100);
free(p);
free(p);
return 0;
}
6.动态开辟空间忘记释放
void test()
{
int* p = (int*)malloc(100);
if (p == NULL)
{
return;
}
}
int main(void)
{
test();
//函数调用结束后,p作为局部变量被销毁,找不到malloc开辟的空间了
//对于不停运存的服务器,其造成内存泄漏
return 0;
}