C进阶:动态内存函数 malloc calloc realloc free及常见动态内存开辟错误(下)

简介: C进阶:动态内存函数 malloc calloc realloc free及常见动态内存开辟错误(下)

实例:

1. #include <stdio.h>
2. #include <stdlib.h>
3. #include <string.h>
4. 
5. 
6. int main()
7. {
8. /* 最初的内存分配 */
9. char *str = (char *) malloc(15);
10. if(str==NULL)    //判断内存是否开辟成功
11.    {  
12. perror("malloc");
13. return 0;
14.    }
15. strcpy(str, "runoob");
16. printf("String = %s,  Address = %p\n", str, str);
17. 
18. /* 重新分配内存 */
19. char *ptr = (char *) realloc(str, 25);
20. if(ptr==NULL)   //判断内存是否重新分配成功
21.    {
22. perror("realloc");
23. return 0;
24.    }
25.    str=ptr;    //分配成功将重新开辟的内存的首地址赋给原指针
26. strcat(str, ".com");
27. printf("String = %s,  Address = %p\n", str, str);
28. 
29. free(str);  //释放开辟的内存空间
30.    str=NULL;   //指针置空
31. 
32. return 0;
33. }

四.常见的动态内存错误

1.对NULL指针的解引用操作

例:

1. int main()
2. {
3.  int* arr = (int*)malloc(1000000000000000);
4.  *arr = 1;
5.  printf("%d\n", *arr);
6.  free(arr);
7.  arr = NULL;
8.  return 0;
9. }

有时候由于我们未对动态开辟的内存检查,而导致我们后面使用了空指针;

调试时发现arr是空指针,所以程序什么也没有输出;

所以在使用完动态内存开辟函数后,一定要对返回值进行检查!


2.对动态开辟空间的越界访问

其实这就和数组类似,数组不能越界访问,动态开辟的空间也不能越界访问;

例:

1. int main()
2. {
3.  int* arr = (int*)malloc(5 * sizeof(int));   //开辟5个元素的空间
4.  int i = 0;
5.  for (i = 0; i < 10; i++)
6.  {
7.    arr[i] = i;
8.  }
9.  free(arr);
10.   arr = NULL;
11.   return 0;
12. }


3.对非动态开辟内存使用free释放

上文中讲到这是C标准未定义的,所以取决于编译器,编译器不同,对这种情况的处理也不同;

下面我们来看看在 vs2022 中是怎么处理这种情况的:

可以看到程序直接崩溃了,所以最好还是要避免这种情况。


4.使用free释放一块动态开辟内存的一部分

例:

1. int main()
2. {
3.  int* p = (int*)malloc(5 * sizeof(int));
4.  if (p == NULL)
5.  {
6.    perror("malloc");
7.    return 0;
8.  }
9.  *p++ = 1;  //改变p指针的位置
10.   free(p);
11.   p = NULL;
12.   return 0;
13. }

程序又直接崩溃了,所以不可以乱动 p 的位置,否则将会导致较为严重的后果;


5.对同一块动态内存多次释放

例:

1. int main()
2. {
3.  int* p = (int*)malloc(20);
4.  free(p);
5.  free(p);
6.  p = NULL;
7.  return 0;
8. }

程序再次崩溃。


6.动态开辟内存忘记释放(内存泄漏)

当我们开辟完动态内存,却忘记使用free函数释放,这就会导致内存泄漏的问题,刚开是我们并不会注意到,可是当时间久了,你就会发现你的电脑越来越卡,你的电脑的内存快被吃完了;所以使用free函数释放所开辟的内存空间是一定不能忘记的。

1. void test()
2. {
3. int *p = (int *)malloc(100);
4. if(NULL != p)
5.     {
6.         *p = 20;
7.     }
8. }
9. int main()
10. {
11. test();
12. while(1);
13. return 0;
14. }

以上代码运行起来时,按电脑上的  ctrl + shift + esc  打开任务管理器,你就会发现这个程序一直在吃内存。


😄😁本文到此就结束了,如有错误或是建议,欢迎小伙伴们提出;😊🙂

🤩🥰希望小伙伴能支持支持博主啊,你们的支持对我很重要;😆😍

🕊️👻谢谢你的阅读。🤖🐬


目录
相关文章
|
28天前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
31 3
|
20天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
16天前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
15 0
|
29天前
|
C语言 C++
c语言回顾-内存操作函数
c语言回顾-内存操作函数
39 0
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
339 0
|
15天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
30 1
|
19天前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
24天前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
28天前
|
存储 编译器
数据在内存中的存储
数据在内存中的存储
37 4
|
27天前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
48 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配