Search code examples
clistlinked-listdoubly-linked-listdestroy

Why is my tail still pointing to Something instead of pointing to NULL after I destroy the list


so I wrote this code in c that does basic doubly linked list tasks like create the list, insert a node after/before a given current NODE, removes a given current Node and So on, but I ran into this issue when I tried to destroy the list. What's happening is, when I destroy the list, it deallocates all Nodes properly (at least I think so from what I see in the debugger watch), but when I check to see whether the head and tail pointer point to NULL since the Nodes no longer exists, the head points to NULL, but my tail still points to something that I'm not sure whether it is a node from the list that wasn't deallocated properly or something else.

Can someone tell me what's happening? Here is the relevant code;

This is the function that Deallocates all nodes, thus destroying the list

void DListDestruct(DList* list) {
DListNode* tempHead = list->head;;

while (tempHead != NULL) {
    tempHead = tempHead->next;
    free(list->head);
    list->head = tempHead;
}

if (list->tail == NULL) {
    list->size = 0;
}


}


    //Creation of the structs for the list    

typedef struct DListNode_struct {
   char *str;
   int blankIndex;
   int blankLength;
   struct DListNode_struct *next;
   struct DListNode_struct *prev;
} DListNode;

typedef struct DList_struct {
   int size;
   DListNode *head;
   DListNode *tail;
} DList;



/* This creates a new list and initializes the head/tail */

void DListConstruct(DList* list) {

    list->head = NULL;
    list->tail = NULL;
    list->size = 0;

}


/* inserts newNode after the given currNode */

void DListInsertAfter(DList* list, DListNode* currNode, DListNode* newNode) {

DListNode* sucNode = NULL;

if (list->head == NULL) {
    list->head = newNode;
    list->tail = newNode;
    list->size = list->size++;
}

else if (currNode == list->tail) {
    list->tail->next = newNode;
    newNode->prev = list->tail;
    list->tail = newNode;
    list->size = list->size++;
}

else {
    sucNode = currNode->next;
    newNode->next = sucNode;
    newNode->prev = currNode;
    currNode->next = newNode;
    sucNode->prev = newNode;
    list->size = list->size++;
}
}


/* inserts newNode before the given currNode */
void DListInsertBefore(DList* list, DListNode* currNode, DListNode* newNode) {
DListNode* predNode;


if (list->head == NULL) {
    list->head = newNode;
    list->tail = newNode;
    list->size = list->size++;
}

else if (currNode->prev != NULL) {
    predNode = currNode->prev;
    newNode->next = currNode;
    newNode->prev = predNode;
    currNode->prev = newNode;
    predNode->next = newNode;
    list->size = list->size++;
}

else if (currNode->prev == NULL) {
    newNode->next = currNode;
    currNode->prev = newNode;
    list->head = newNode;
    list->size = list->size++;
}

}

So again, Why is it that when I destroy the List, using the DListDestroy function (the first one on top), all nodes are deallocated, the head pointer points to NULL, but the tail pointer still points to something?

Thanks in advance!


Solution

  • That's because the tail stil points to the address of the node you freed, so now it points to some garbage.

    The head points to wherever "tempHead" points and by the end of the loop it points to null, because during the insertion process, you put null in the next of the last node.

    In conclusion, the tail points to the address of the last node, which is garbage. The head points to the last node's next which is NULL.