1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include "mainc26.h"
  5. struct TelPhone{
  6. char name[];
  7. char TelNumber[];
  8. struct TelPhone* next;
  9. };
  10. int mainc26()
  11. {
  12.  
  13. setbuf(stdout, NULL);
  14. //fflush(stdout);
  15. struct TelPhone *head = NULL;
  16. struct TelPhone *pre,*current;
  17. char input[];
  18. printf("请输入联系人的姓名:\n");
  19. fflush(stdout);
  20. while(gets(input) != NULL && input[] != '\0')
  21. {
  22. current = (struct TelPhone*)malloc(sizeof(struct TelPhone));
  23. if(head == NULL)
  24. head = current;
  25. else
  26. pre->next = current;
  27. current->next = NULL;
  28. strcpy(current->name,input);
  29. printf("请输入联系人的电话号码:\n");
  30. scanf("%s",current->TelNumber);
  31. while(getchar() != '\n')
  32. continue;
  33. printf("请输入下一个联系人(空行则退出):\n");
  34. pre = current;
  35. }
  36. if(head == NULL)
  37. printf("电话里面没有储存任何数据:");
  38. else
  39. puts("通讯录:");
  40. current = head;
  41. while(current != NULL)
  42. {
  43. printf("%s:%s\n",current->name,current->TelNumber);
  44. current = current->next;
  45. }
  46. current = head;
  47. int n=;
  48. while(current != NULL)
  49. {
  50. n++;
  51. printf("this is %d time \n",n);
  52. free(current);
  53. current=NULL;
  54. printf("cur.name %s ,",current->name);
  55. printf("cur.teln %s ,",current->TelNumber);
  56. // printf("cur.name %p ,",current->next);
  57. printf("\n");
  58. current = current->next;
  59. }
  60. return ;
  61. }

在 line 53中 使用free(current) ,这里似乎是将current的内存释放,然后实际上,这里的释放后,其内存信息已经存在,

如果将line 54的current=null,注释,该程序仍能正确运行,并通过该链表将内存释放掉,而实际上这种问题时错误的。

通过百度,我查到

问题如下:

  1. 代码如下:
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4.  
  5. struct test
  6. {
  7. int a;
  8. struct test *next;
  9. };
  10. int main()
  11. {
  12. struct test test0={};
  13. struct test *test1 = (struct test *)malloc(sizeof(struct test));
  14. test1->a=;
  15. test1->next = &test0;
  16. free(test1);
  17. printf("%d %d",test1->a,(*test1->next).a);
  18.  
  19. }
  20. 输出test1->a0 ,(*test1->next).a10
  21.  
  22. 说明结构体里的变量a已经被free释放掉了,而test1的指针next却还可以被访问

解答如下

  1. free函数,实际上做的事情不是真正的释放内存。
    首先你要清楚,内存是由操作系统来管理的(操作包括分配、释放等)。
    系统中的内存在c语言分配内存机制上被分为很多个块,c的底层代码用数据结构chunk来表示。chunk中有一个标志位,用来表示该内存块是否为待分配或者已分配状态。每一次调用malloc,这个标志位会被设置1(好像是1,记不太清楚了),调用free时被设置为0. 操作系统的内存管理机制会根据这个值来分配和释放内存。
    也就是说调用free的时候,只是设置了这个标志位(当然还做了其他事,就你这个问题而言,只讨论这个),而内存还原封不动的在那里。所以,当你在系统真正释放这个内存之前再次访问这个地址,你会得到你想要的结果。
    说明,“输出test1->a0”,这个的原因可能是free的时候,设置chunk块的标志位时,覆盖了a的值。chunk数据结构中,第一个字节的前8位是标志位,后面还有24位也有各自的用处。具体是什么导致a的值为0的,你有兴趣的话,你可以自己去研究。可以去阅读linuxglibc源码。
    "(*test1->next).a为10",就简单了。next偏移struct test所占内存的“头(head)”距离较远,free的时候的一些设置值的操作没有影响到,能访问到这个指针的值,并且test0还在函数栈中完整保留,自然就能访问到了。
  2.  
  3. P.S c/C++的malloc/freenew/delete都有这个特性,所以编程的时候要养成一个良好习惯,在调用freedelete的时候要将指针赋值为NULL,如:
    free(ptr);
    ptr=NULL;
    或者
    delete ptr;
    ptr=NULL;
  4.  

  1. 所以这里和回答的问题比较相符,
    实际上freecurrent)以后,其内存的实际内容 并没有被释放,仍然可以使用,但这样是应该,
    应该讲内存释放后的变量赋值为NULL.
    那么单项链表的内存该如何释放呢??
  2.  
  3. 可以参考如下的代码,将其释放
  1. //释放内存
  2. struct TelPhone * temp;
  3. while(current != NULL)
  4. {
  5. n++;
  6.  
  7. printf("this is %d time \n",n);
  8. printf("cur.name %s ,",current->name);
  9. printf("cur.teln %s ,",current->TelNumber);
  10. printf("cur.name %p ,",current->next);
  11. printf("\n");
  12.  
  13. temp=current;
  14. current=current->next;
  15. free(temp);
  16. temp=NULL;
  17. }
  1.  

关于free的使用疑惑的更多相关文章

  1. Atitit 图像处理的心得与疑惑 attilax总结

    Atitit 图像处理的心得与疑惑 attilax总结 1.1. 使用类库好不好??还是自己实现算法1 1.2. 但是,如果遇到类库体积太大,后者没有合适的算法,那就只能自己开发算法了1 1.3. 如 ...

  2. 每日一记-mybatis碰到的疑惑:String类型可以传入多个参数吗

    碰到一个觉得很疑惑的问题,Mybatis的parameterType为String类型的时候,能够接收多个参数的吗? 背景 初学Mybatis的时候,看的教程和书籍上都是在说基本的数据类型如:int. ...

  3. 解决上一篇jquery中on的疑惑

    内容都是来自:http://www.365mini.com/page/jquery-on.htm.这里做一下收藏.文章的最后  疑问和解答可以解决所有的疑惑  看了之后能更好的整篇文章. on()函数 ...

  4. ConcurrentDictionary线程不安全么,你难道没疑惑,你难道弄懂了么?

    前言 事情不太多时,会时不时去看项目中同事写的代码可以作个参考或者学习,个人觉得只有这样才能走的更远,抱着一副老子天下第一的态度最终只能是井底之蛙.前两篇写到关于断点传续的文章,还有一篇还未写出,后续 ...

  5. Python处理json格式的数据文件(一些坑、一些疑惑)

    这里主要说最近遇到的一个问题,不过目前只是换了一种思路先解决了,脑子里仍然有疑惑,只能怪自己太菜. 最近要把以前爬的数据用一下了,先简单的过滤一下,以前用scrapy存数据的时候为了省事也为了用一下它 ...

  6. SQL Server中的索引结构与疑惑

    说实话我从没有在实际项目中使用过索引,仅知道索引是一个相当重要的技术点,因此我也看了不少文章知道了索引的区别.分类.优缺点以及如何使用索引.但关于索引它最本质的是什么笔者一直没明白,本文是笔者带着这些 ...

  7. python的正则表达式 re-------可以在字符串前加上 r 这个前缀来避免部分疑惑,因为 r 开头的python字符串是 raw 字符串,所以里面的所有字符都不会被转义

    正则表达式使用反斜杆(\)来转义特殊字符,使其可以匹配字符本身,而不是指定其他特殊的含义.这可能会和python字面意义上的字符串转义相冲突,这也许有些令人费解.比如,要匹配一个反斜杆本身,你也许要用 ...

  8. jquery 清除动画队列不疑惑

    $(this).siblings().stop().fadeTo(200, 0.3); jquery动画存在一个队列, 会把事件产生的动画 放在一个队列中,当来不及执行这些事件队列的时候,会在事件结束 ...

  9. 对Joint Training of Cascaded CNN for Face Detection一文的几点疑惑

    最近读了Joint Training of Cascaded CNN for Face Detection这篇论文,论文中把之前人脸检测使用到的cascade cnn,从分开训练的模式,改为了联合训练 ...

  10. 关于flume中的几个疑惑

    文章发自http://www.cnblogs.com/hark0623/p/4205756.html  转载请注明 flume越用越有一些疑惑,这个月中按计划是要阅读flume源码的,我希望能解决我的 ...

随机推荐

  1. MySQL Community Server 8.0.16

    1 首先 我们需要先下载一个 Mysql 点击这个网址进入 Mysql 的官网的下载地址: https://dev.mysql.com/downloads/mysql/ 首先 根据你的电脑的操作系统选 ...

  2. 移动端1px边框解决方案

    在retina屏中,像素比为2(iPhone6/7/8)或3(iPhone6Plus/7Plus/8Plus),1px的边框看起来比真的1px更宽. 使用伪类加transform的方式 元素本身不定义 ...

  3. Mysql 语句 insert into 与 replace into 区别

    []insert into 与 replace into 区别 replace into 的运行与insert into 很相似.不同点: 若表中的一个旧记录与一个用于PRIMARY KEY 或 一个 ...

  4. strlen()与sizeof()

    一.strlen() strlen()为计算字符串长度的函数,以‘\0’为字符串结束标志.注意:其传入参数必须是字符串指针(char*), 当传入的是数组名时,实际上数组退化成指针了. 二.sizeo ...

  5. Go语言【学习】defer和逃逸分析

    defer 什么是defer? defer是Go语言的一中用于注册延迟调用的机制,使得函数活语句可以再当前函数执行完毕后执行 为什么需要defer? Go语言提供的语法糖,减少资源泄漏的发生 如何使用 ...

  6. 2. 运行Spark Streaming

    2.1 IDEA编写程序 Pom.xml加入以下依赖: <dependency> <groupId>org.apache.spark</groupId> <a ...

  7. SSM整合学习 一

    一:新建maven项目 File--New Project选择maven项目下的maven-archetype-webapp,输入GroupId.Artifactld,选择maven信息,新建mave ...

  8. golang --- time包常用函数以及基础的类型转换

    1.[]byte转为string: package main import ( "fmt" ) func main() { data := [4]byte{0x31, 0x32, ...

  9. Maven的仓库和settings.xml配置文件

    (尊重劳动成果,转载请注明出处:https://blog.csdn.net/qq_25827845/article/details/83549846冷血之心的博客) 快速导航: Maven基础概念和安 ...

  10. springboot使用HttpSessionListener 监听器统计当前在线人数

    概括: request.getSession(true):若存在会话则返回该会话,否则新建一个会话. request.getSession(false):若存在会话则返回该会话,否则返回NULL ht ...