仍然能够访问已释放的结构

时间:2014-05-28 19:14:47

标签: c struct free c99

所以,我有一个结构:

tyepdef struct node {
    struct node *next;
    double value;
} NodeT, *NodeTP;

我有三个功能:

int deleteNode(NodeTP p)
{
    free(p);
    p = NULL;

    return 1;
}

int deleteOne(NodeTP list)
{
    if (list->next != NULL)
        deleteOne(list->next);
    else 
        deleteNode(list);

    return 1;
}

int print(NodeT list)                                                           
{                                                                               
    printf("%lf\n", list.value);                                                

    if (list.next != NULL)                                                      
        print(*list.next);                                                      

    return 1;                                                                   
}   

deleteOne会将列表中的最后一个节点传递给deleteNode,以便释放内存。初始化节点时,除非需要,否则不会为下一个节点分配内存。相反,它最初设置为NULL。这就是为什么我不能自由(p->接下来)。

所以,如果我有一个节点列表(让他们说他们的值是3.5,2.5,1.2,3.6) 打印功能将打印以下内容:

3.5
2.5
1.2
3.6

然后,如果删除了最后一个节点,并再次打印,则打印以下内容:

3.5
2.5
1.2
3.6

如果删除另一个节点,我会收到错误,因为我试图释放已经释放的内存。

好像打印正在访问内存位置,已经被释放了。但是,如果下一个“下一个”,它似乎不应该尝试阅读这个内容。 node等于NULL。 我意识到这是未定义的行为,但我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

删除链接列表的tail node后,程序员有责任设置之前的链接列表。节点的next元素为NULL。

tail nodefree()时,节点占用的内存将继续保留已分配的值(当它是节点时),直到该内存用于其他目的。因此,在释放它之后继续引用该内存并不是一个好主意。

有时,我会编写自己的free()函数,以确保传递给free的指针不再能够访问内存。像这样:

void myFree(void **ptr)
   {
   free(*ptr);
   *ptr=NULL;
   }

然后,当释放尾节点时,父节点的下一个指针自动设置为NULL:

void myFreeTailNode(NodeT **head)
   {
   NodeT *parentNode   = NULL;

   if(NULL == head)
      return;

   if(NULL == *head)
      return;

   if(NULL == (*head)->next)
      myFree((void **)head);
   else
      {
      for(parentNode = *head; parentNode->next->next; parentNode=parentNode->next)
          /*Do Nothing */ ;

      MyFree((void **)&parentNode->next);
      }
   }

答案 1 :(得分:0)

如果要在函数外部分配NULL,则应该执行此操作:

int deleteNode(NodeTP * p)
{
    free(*p);
    *p = NULL;

    return 1;
}

将您的调用更改为deleteNode。