Still able to access a struct that has been freed [duplicate]

非 Y 不嫁゛ 提交于 2019-12-13 10:54:41

问题


So, I have a struct:

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

and I have three functions:

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 will hand the final node in the list to deleteNode so that the memory can be freed. When a node is initialized, no memory is allocated for next, until it is needed. instead, it is initially set to be NULL. This is why I don't free(p->next).

So, if I have a list of nodes (let's say their values are 3.5, 2.5, 1.2, 3.6) the print function will print the following:

3.5
2.5
1.2
3.6

Then, if the final node is deleted, and I print again, the following is printed:

3.5
2.5
1.2
3.6

If I delete another node, I get an error because I'm trying to free memory that has already been freed.

It seems as though print is accessing a memory location still, that has already been freed. However, it seems like it shouldn't be trying to read this if the 'next' node is equal to NULL. I realize this is undefined behaviour, but how can I fix this?


回答1:


When the tail node of a linked list is deleted, it is the programmer's responsibility to set the previous' node's next element to NULL.

When the tail node is free()ed, the memory that the node occupied will continue to hold the values it was assigned (when it was a node) until that memory is used for another purpose. Hence, it is not a good idea to continue to reference that memory after freeing it.

Sometimes, I write my own free() function to ensure that the pointer passed to free is no longer capable of accessing the memory. Something like this:

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

Then, when the tail node is freed, the parent node's next pointer is automatically set to 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);
      }
   }



回答2:


You should do this if you want NULL assigned outside the function:

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

    return 1;
}

And change your calls to deleteNode.



来源:https://stackoverflow.com/questions/23920057/still-able-to-access-a-struct-that-has-been-freed

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!