免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3859 | 回复: 8
打印 上一主题 下一主题

[C] free 一个 struct 后,其内部指针依然可以访问? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-09-05 09:53 |只看该作者 |倒序浏览
本帖最后由 木卫十二 于 2012-09-05 09:55 编辑

单链表结构体:

  1. typedef struct node {
  2.     char        *item;
  3.     struct node *next;
  4. } *link;
复制代码
在做 free 操作后,依然可以遍历整个链表,只是值全部为零。甚至设置 head = NULL; 也不行。请问这种情况正常吗?
free 操作,对结构体做了哪些改变?

  1. void destroy(link head)
  2. {
  3.     printf("destroy(link)\n");
  4.    
  5.     link temp = head;
  6.     for(;;)
  7.     {
  8.         head = temp;
  9.         temp = temp->next;
  10.         
  11.         printf("free item => [%s]\n", head->item);
  12.         free(head);
  13.         head = NULL;
  14.         
  15.         if (temp == NULL)
  16.             break;
  17.     }
  18.    
  19.     printf("\n");
  20. }
复制代码
gdb 下调试,看起来 free 并未改变指针地址, 设为 head = NULL 后改变了。但后期 traverse 的时候, head 的地址依然未变。请看下 void destroy(link head) 函数,有什么问题吗?谢谢!
  1. Breakpoint 1, destroy (head=0x804b008) at link.c:60
  2. 60                free(head);
  3. (gdb) print head
  4. $1 = (link) 0x804b008
  5. (gdb) n
  6. 61                head = NULL;
  7. (gdb) print head
  8. $2 = (link) 0x804b008
  9. (gdb) n
  10. 63                if (temp == NULL)
  11. (gdb) print head
  12. $3 = (link) 0x0
  13. (gdb)
复制代码
  1. traverse(link)
  2. 226            if (head == NULL)
  3. (gdb) print head
  4. $1 = (link) 0x804b008
复制代码
另外, 下面是我写的单链表操作的实践,能否请看下实现的思路有没有问题?谢谢!
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. typedef struct node {
  4.     char        *item;
  5.     struct node *next;
  6. } *link;


  7. void destroy(link);
  8. link initialize();
  9. void delete(link, int);
  10. void insert(link, int, char *);
  11. link search(link, char *);
  12. void pop(link);
  13. void push(link, char *);
  14. void traverse(link);

  15. int main()
  16. {
  17.     link linkhead = initialize();
  18.     pop(linkhead);
  19.    
  20.     push(linkhead, "test1");
  21.     push(linkhead, "test2");
  22.     push(linkhead, "test3");
  23.     push(linkhead, "test4");
  24.     push(linkhead, "test5");
  25.     push(linkhead, "test2");
  26.     push(linkhead, "test7");
  27.    
  28.     pop(linkhead);
  29.     push(linkhead, "test3");
  30.     delete(linkhead, 3);
  31.    
  32.     traverse(linkhead);
  33.    
  34.     insert(linkhead, 2, "replace 2");
  35.     traverse(linkhead);
  36.    
  37.     search(linkhead, "test2");
  38.    
  39.     destroy(linkhead);
  40.    
  41.     traverse(linkhead);
  42. }


  43. void destroy(link head)
  44. {
  45.     printf("destroy(link)\n");
  46.    
  47.     link temp = head;
  48.     for(;;)
  49.     {
  50.         head = temp;
  51.         temp = temp->next;
  52.         
  53.         printf("free item => [%s]\n", head->item);
  54.         free(head);
  55.         head = NULL;
  56.         
  57.         if (temp == NULL)
  58.             break;
  59.     }
  60.    
  61.     printf("\n");
  62. }

  63. link initialize()
  64. {
  65.     printf("initialize()\n");
  66.    
  67.     link head = malloc(sizeof(link));
  68.    
  69.     head->item = "I'm the head!";
  70.     head->next = NULL;
  71.    
  72.     printf("\n");
  73.    
  74.     return head;
  75. }

  76. void delete(link head, int i)
  77. {
  78.     printf("delete(link, int); delete the [%d]'th item.\n", i);
  79.    
  80.     link temp    = head;
  81.    
  82.     int j = 0;
  83.    
  84.     for(;;)
  85.     {
  86.         if (temp->next == NULL)
  87.         {
  88.             break;
  89.         }
  90.         
  91.         if ((i-1) == j)
  92.         {
  93.             temp->next = temp->next->next;
  94.             break;
  95.         }
  96.         
  97.         temp = temp->next;
  98.         j++;
  99.     }
  100.    
  101.     printf("\n");
  102. }


  103. void insert(link head, int i, char *item)
  104. {
  105.     printf("insert(link, int, char *); insert item => [%s] as the [%d]'th.\n", item, i);
  106.    
  107.     link temp    = head;
  108.     link newitem = malloc(sizeof(link));
  109.    
  110.     newitem->item = item;
  111.    
  112.     int j = 0;
  113.    
  114.     for(;;)
  115.     {
  116.         if (temp->next == NULL)
  117.         {
  118.             break;
  119.         }
  120.         
  121.         if ((i-1) == j)
  122.         {
  123.             newitem->next = temp->next;
  124.             temp->next = newitem;
  125.             break;
  126.         }
  127.         
  128.         temp = temp->next;
  129.         j++;
  130.     }
  131.    
  132.     printf("\n");
  133. }

  134. link search(link head, char *item)
  135. {
  136.     printf("search(link, item); item => [%s]\n", item);
  137.    
  138.     link temp = head;
  139.     int  i    = 0;
  140.      
  141.     for(;;)
  142.     {
  143.         if (strcmp(temp->item, item) == 0)
  144.         {
  145.             printf("found item [%s] at the %d'th item.\n", temp->item, i);
  146.         }
  147.         
  148.         if (temp->next == NULL)
  149.         {
  150.             break;
  151.         }
  152.         
  153.         temp = temp->next;
  154.         i++;
  155.     }
  156.    
  157.     printf("\n");
  158. }

  159. void pop(link head)
  160. {
  161.     printf("pop(link)\n");
  162.    
  163.     link temp = head;
  164.    
  165.     for(;;)
  166.     {
  167.         if (temp->next == NULL)
  168.         {
  169.             printf("only head item exist. so, don't pop.\n");
  170.             break;
  171.         }
  172.         else if (temp->next->next == NULL)
  173.         {
  174.             printf("pop item: %s\n", temp->next->item);
  175.             temp->next = NULL;
  176.             break;
  177.         }
  178.         
  179.         temp = temp->next;
  180.     }
  181.    
  182.     printf("\n");
  183. }

  184. void push(link head, char *item)
  185. {
  186.     printf("push(link, item); item => '%s'\n", item);
  187.    
  188.     link newitem = malloc(sizeof(struct node));
  189.     link temp    = head;
  190.    
  191.     newitem->item = item;
  192.     newitem->next = NULL;
  193.    
  194.     for(;;)
  195.     {
  196.         if(temp->next == NULL)
  197.         {
  198.             printf("puch item %s\n", item);
  199.             temp->next = newitem;
  200.             break;
  201.         }
  202.         
  203.         temp = temp->next;
  204.     }
  205.    
  206.     printf("\n");
  207. }

  208. void traverse(link head)
  209. {
  210.     printf("traverse(link)\n");

  211.     if (head == NULL)
  212.     {
  213.         printf("linkhead is NULL!\n");
  214.         exit(0);
  215.     }
  216.    
  217.     link temp = head;
  218.     for(;;)
  219.     {
  220.         if(temp->next == NULL)
  221.             break;
  222.         
  223.         /* print all, except head. */
  224.         temp = temp->next;
  225.         printf("get item = %s\n", temp->item);
  226.     }
  227.    
  228.     printf("\n");
  229. }
复制代码

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
2 [报告]
发表于 2012-09-05 10:00 |只看该作者
释放了再访问,就是未定义行为

论坛徽章:
0
3 [报告]
发表于 2012-09-05 10:07 |只看该作者
谢谢。是不是可以这样理解:这处结构体已不再使用,我也已经释放了对应的内存。正常情况下就不需要再管他们了,继续遍历访问他们反而是非正常操作? 回复 2# hellioncu

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
4 [报告]
发表于 2012-09-05 10:08 |只看该作者
木卫十二 发表于 2012-09-05 10:07
谢谢。是不是可以这样理解:这处结构体已不再使用,我也已经释放了对应的内存。正常情况下就不需要再管他 ...


是绝对不能再去访问那块内存

论坛徽章:
0
5 [报告]
发表于 2012-09-05 10:10 |只看该作者
噢,谢谢! 回复 4# hellioncu


   

论坛徽章:
0
6 [报告]
发表于 2012-09-05 10:46 |只看该作者
能访问是一回事,出不出问题又是一回事。

论坛徽章:
0
7 [报告]
发表于 2012-09-05 13:00 |只看该作者
释放后访问结果是未定义的     能遍历只是那块内存的东西尚未被覆盖而已

论坛徽章:
0
8 [报告]
发表于 2012-09-05 16:34 |只看该作者
不能确定值得区域访问的到也是不靠谱的

论坛徽章:
0
9 [报告]
发表于 2012-09-05 18:40 |只看该作者
got it. Thanks!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP