写点什么

【C 语言】动态内存分配,nginx 调优与监控

作者:Java高工P7
  • 2021 年 11 月 10 日
  • 本文字数:1752 字

    阅读完需:约 6 分钟

for (i = 0; i < 10; i++)


printf("%d ",*(arr + i));


//记得释放所开辟的空间


free(arr);


return 0;


}


二、calloc




void* __calloc (size_t num, size_t** size );


返回类型:与 malloc 函数是一样的,就不在多说了。


函数参数:size_t num, 需要开辟多少个元素的空间。


? size_ size, 每一个元素,所占用的内存空间是多少个字节。


:与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全 0。


栗子:


#include <stdlib.h>


#include <stdio.h>


int main()


{


//还是申请 10 个 int 类型的内存空间


int* arr = (int*)calloc(10, sizeof(int));


if (arr == NULL)


{


perror("calloc"); //calloc 开辟空间的话,会返回 NULL


return 1;


}


//不做赋值运算,直接输出刚开辟的空间,看是否是已经初始化为 0 了


int i = 0;


for (i = 0; i < 10; i++)


printf("%d ",*(arr + i));


//记得释放空间


free(arr);


return 0;


}


三、realloc




void* **realloc(*void memb


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


lock, size_t size);


作用: Reallocate memory blocks.(重新分配内存块)


  • memblock 是需要调整的内存地址

  • size 调整之后新大小

  • 返回值为调整之后的内存起始位置。

  • 这个函数调整原内存空间大小的基础_上,还会将原来内存中的数据移动到新的空间。

  • realloc 在调整内存空间的是存在两种情况:


? 情况 1 :原有空间之后有足够大的空间


?



假设我还想为“红色框内的内存空间,扩大一倍,并且在这块空间的后面,是有足够的空间。所有 realloc 函数会在这紧挨这红色框后面直接开辟空间。并且返回的还是红色框的首元素地址。


情况 2: 原有空间之后没有足够大的空间



此时,如果我还想为红色框的内存空间进行扩大,此时红色框后面紧挨着的空间已经被其他程序所占用了,此时想开辟空间的话,只能将现在这块空间先释放掉(realloc 会自动释放),再去其他大一点的地方进行开辟空间。


如图:



:realloc 函数,有一个很值得注意的地方,看如下代码:


int main()


{


int* arr = (int*)malloc(5 * sizeof(int)); //先开辟 5 个 int 类型的空间


if (arr == NULL)


return 1;


//此时,我觉得 malloc 开辟的空间小了,我想增加


arr = (int*) realloc(arr, 10);


free(arr);


return 0;


}


大家觉得,这段代码,有什么弊端?


分析:


在第 8 行,realloc 函数,去调整 arr 的空间。他是先查看 arr 后面的内存空间是否够用,如果不够用的话,会去寻找其他大一点的地方去开辟空间。假设此时我的内存已经满了,此时 realloc 返回的是 NULL。


也就是说,我本来想增容,结果没增成功,还把以前空间里的数据弄丢了。


所以在使用 realloc 函数时,先使用一个临时变量进行保存一下,如果返回不是 NULL,我们在把返回的内存地址赋值给 arr 即可。


如下:


int main()


{


int* arr = (int*)malloc(5 * sizeof(int)); //先开辟 5 个 int 类型的空间


if (arr == NULL)


return 1;


//此时,我觉得 malloc 开辟的空间小了,我想增加


int* tmp = NULL;


tmp = (int*) realloc(arr, 10);


if (tmp != NULL)


arr = tmp;


free(arr);


return 0;


}


四、常见的动态内存的错误




  • 对 NULL 进行解引用操作


int main()


{


int* arr = (int*)malloc(10 * sizeof(int));


*arr = 10; //没有对 arr 进行 NULL 的判断


free(arr);


return 0;


}


  • 对非动态内存分配的空间进行 free 释放


int main()


{


int a = 10;


int* pa = &a;


free(pa); //pa 指针,并不是 malloc 等函数开辟的空间,不能使用 free 释放,系统会自动回收的


return 0;


}


  • 使用 free 函数释放一块动态分配空间的一部分


int main()


{


int* arr = (int*)malloc(10 * sizeof(int));


if (arr == NULL)


return 1;


arr++; //此时,arr 向后跳了 4 个字节


free(arr); //现在再去释放空间,最前面的 4 个字节的空间就没有释放到,会报错


return 0;


}


  • 对同一块内存空间进行多次释放


int main()


{


int* arr = (int*)malloc(10 * sizeof(int));


if (arr == NULL)


return 1;


free(arr);


free(arr); //重复释放了


return 0;


}


  • 动态开辟的空间忘记释放(内存泄漏)


int main()


{


int* arr = (int*)malloc(10 * sizeof(int));


if (arr == NULL)


return 1;


//没有释放空间,会造成内存泄漏


//造成内存泄漏,有很多原因,例如,在调用其他函数时,想传回到本函数,指针没用正确,导致开辟的空间没有传回来等等


return 0;


}


注: 动态开辟的内存空间,切记 一定要释放。不然后果很严重的!!!

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
【C语言】动态内存分配,nginx调优与监控