TransWikia.com

Another problem with unload function, node set to null is repopulating somehow

Stack Overflow Asked by Pleasant Nightmares on September 9, 2020

I’m making a function to free a hash table from memory. At the moment, I’m only attempting to set the nodes to NULL to make sure that it’s iterating correctly. But I’m getting output that I don’t understand.

This is my current hash table:

enter image description here

This is my current output. It’s an infinite loop:

enter image description here

And this is my code:

bool unload(void)
{
    // For all elements in the hash table
    for (int i = 0; i < N; i++) 
    {
        // Until break...
        while (1)
        {
            // Set traversal node at hash index i, set trailing traversal node to NOLL
            node *curr = table[i];
            printf("start CURR WORD: %s (%p)n", curr->word, curr); // DEBUG
            node *prev = NULL;

            // If current is NULL, meaning the index head is null, break
            if (curr == NULL)
            {
                printf("CURR is NULL: BREAKING...n"); // DEBUG
                break;
            }
            
            // if the index head is not NULL, but its' next pointer is NULL, set current to NULL, next iteration
            if (curr->next == NULL)
            {
                printf("HEAD (%s)->Next: NULL, SETTING HEAD TO NULL...n", curr->word); // DEBUG
                curr = NULL;
                continue;
            }

            // While current is not null, set trailing traversal node to current, set current to its next pointer
            while (curr != NULL)
            {
                printf("CURR is not NULL: (%s), NEXT...n", curr->word); // DEBUG
                prev = curr;
                curr = curr->next;
            }

            // when current is NUll, set trailing traversal node to NULL
            printf("CURR IS NULL, SETTING PREVIOUS (%s) TO NULL...n", prev->word);
            prev = NULL;
            printf("PREV WORD: %sn", prev->word);
        }
    }

    return true;
}

The first if condition, if (curr == NULL), seems to be triggering just fine. table[0] is NULL, so it breaks the first iteration of while (1). What the rest is doing, I don’t understand. As intended, it will skip the first two nodes, landing on NULL. Then, apparently, it will set the previous node to NULL, like it’s supposed to. But in the next iteration of while (1), the node that it was supposed to have set to NULL is still populated, despite the command prev = NULL;, and despite the two print statements before and after that command (printf("CURR IS NULL, SETTING PREVIOUS (%s) TO NULL...n", prev->word); and printf("PREV WORD: %sn", prev->word);) triggering as well.

Can someone tell me what’s going wrong here? Why is the node that’s being set to NULL repopulating on the next iteration? Thanks in advance.

EDIT: Here is what I’m trying to achieve…

LIST 00: { } LIST 01: {NODE 1, NODE 2, }

UNTIL THE HEAD IS NULL
    IF the head is NULL
        BREAK

    IF the head is not NULL, but its NEXT pointer is NULL
        Set head to NULL
        next iteration

    IF neither the head nor its next pointer are NULL
        Move to the next node until you reach NULL

    IF the current node is NULL
        Set the previous node to NULL

In List 00, the first IF is met, and it breaks.
In List 01, the third IF is met, and it moves until NULL. Then the fourth IF is met, and the node before it should be set to NULL. At the beginning of iteration 2, it should look like this:

LIST 00: { } LIST 01: {NODE 1, }

In which case, the second IF is met. It should set the head to NULL, and move on to the next iteration:

LIST 00: { } LIST 01: { }

Now, the first IF is met, so it should break the while (1) loop and move on to the next iteration in the for loop.

One Answer

The infinite loop is caused by the while(1) loop. At the top, curr is set to table[i]. In the loop, curr is set to null, but that does not matter because the break statement is never hit and curr is reset to the same value at the top of the loop.

I commented the code to help explain the flow:

bool unload(void)
{
    // For all elements in the hash table
    for (int i = 0; i < N; i++) 
    {
        // Until break...
        while (1)
        {
            // Set traversal node at hash index i, set trailing traversal node to NOLL
            node *curr = table[i];  // <<<<<<< curr set to same value, curr in NOT null, and i is the same as last loop
            printf("start CURR WORD: %s (%p)n", curr->word, curr); // DEBUG
            node *prev = NULL;

            // If current is NULL, meaning the index head is null, break
            if (curr == NULL)  // <<<<<<<<<<<< skip this, curr is NOT null
            {
                printf("CURR is NULL: BREAKING...n"); // DEBUG
                break;  // <<<< never gets here
            }
            
            // if the index head is not NULL, but its' next pointer is NULL, set current to NULL, next iteration
            if (curr->next == NULL)  // <<<<<<<<<  skip this, next is NOT null
            {
                printf("HEAD (%s)->Next: NULL, SETTING HEAD TO NULL...n", curr->word); // DEBUG
                curr = NULL;
                continue;
            }

            // While current is not null, set trailing traversal node to current, set current to its next pointer
            while (curr != NULL)  //  <<<<<<<<<< move curr forward until curr = null
            {
                printf("CURR is not NULL: (%s), NEXT...n", curr->word); // DEBUG
                prev = curr;
                curr = curr->next;
            }
             
            //   <<<<<<<<<<<<<<<<<<<   at this point, curr = null

            // when current is NUll, set trailing traversal node to NULL
            printf("CURR IS NULL, SETTING PREVIOUS (%s) TO NULL...n", prev->word);  // <<<< no curr change
            prev = NULL;                                                             // <<<< no curr change
            printf("PREV WORD: %sn", prev->word);                                   // <<<< no curr change
        }
    }

    return true;
}

------- UPDATE -------

Based on the updated post, this code should achieve the correct result:

bool unload(void)
{
    // For all elements in the hash table
    for (int i = 0; i < N; i++) 
    {
        node *curr = table[i];  // set head
        if (curr == NULL)  continue;  // skip, go to next head
        curr = curr->next; // top of linked list
        
        // set linked list elements to null
        while (curr != NULL) 
        {
            printf("CURR is not NULL: (%s), NEXT...n", curr->word);
            node *prev = curr;
            curr = curr->next
            printf("SETTING PREVIOUS (%s) TO NULL...n", prev->word);
            prev = NULL;
            printf("PREV WORD: %sn", prev->word);
        } // while curr
    } // for i  
}

Answered by Mike67 on September 9, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP