Destroying All Nodes in a Linked List 
Author Message
 Destroying All Nodes in a Linked List

The original posting of this message had an incorrect (and confusing)
subject...

When the statement:

free (*Head);

is used is the pointer *Head set to NULL or must that be done by the
programmer?  Here is my function that destroys all nodes in a linked list of
integers (i.e. all nodes are returned to memory):

void DestroyList (Node **Head)
{
   if ((*Head)->Next != NULL)
      DestroyList (&(*Head)->Next);
   free (*Head);
/* *Head = NULL; **MUST I ADD THIS LINE TO SET THE POINTERS TO NULL? ** */
   return;

Quote:
}

Must I set the pointer, *Head, to NULL myself or does the call to free set
that pointer to NULL for me?  I need to have the pointers set to NULL to
determine if the list is empty or not.

Thanks,

Derek Battams

London, Ontario, Canada



Sun, 30 Jul 2000 03:00:00 GMT  
 Destroying All Nodes in a Linked List

Quote:

> The original posting of this message had an incorrect (and confusing)
> subject...

> When the statement:

> free (*Head);

> is used is the pointer *Head set to NULL or must that be done by the
> programmer?  Here is my function that destroys all nodes in a linked list of
> integers (i.e. all nodes are returned to memory):

> void DestroyList (Node **Head)
> {
>    if ((*Head)->Next != NULL)
>       DestroyList (&(*Head)->Next);
>    free (*Head);
> /* *Head = NULL; **MUST I ADD THIS LINE TO SET THE POINTERS TO NULL? ** */
>    return;
> }

> Must I set the pointer, *Head, to NULL myself or does the call to free set
> that pointer to NULL for me?  I need to have the pointers set to NULL to
> determine if the list is empty or not.

    If you do need NULL, you must set the pointer to NULL.
For further insight into some dark C corners you may have a look
at the enormous thread  named
        Indeterminate values and Undefined behaviour
here in c.l.c

        Regards,
                Alex Krol



Mon, 31 Jul 2000 03:00:00 GMT  
 Destroying All Nodes in a Linked List


Quote:

>void DestroyList (Node **Head)
>{
>   if ((*Head)->Next != NULL)
>      DestroyList (&(*Head)->Next);

Is it a valid assumption that *Head is a valid pointer? You can't
evaluate (*Head)->next if *Head is null.

Quote:
>   free (*Head);
>/* *Head = NULL; **MUST I ADD THIS LINE TO SET THE POINTERS TO NULL? ** */
>   return;
>}

>Must I set the pointer, *Head, to NULL myself or does the call to free set
>that pointer to NULL for me?  I need to have the pointers set to NULL to
>determine if the list is empty or not.

Arguments are passed by value in C. The free() function receives a copy of
the value *Head, not a reference to the object designated by *Head; in other
words, it operates on the rvalue, not the lvalue. Thus it cannot set the value
to NULL.

After you call free on a pointer, that pointer's value becomes indeterminate,
so you _must_ assign some new value to the objects which previously contained
that value before continuing to use those objects. Otherwise your program
invokes undefined behavior.

I wouldn't recommend that you write your list destroyer recursively.
Since lists are linear structures, the function requires O(N) automatic
storage with respect to the size of the list. In many C implementations,
the space for automatic storage is much more limited than other kinds of
storage. There is no need for the list destruction to require any additional
memory if you write it as an iterative loop:

        void DestroyList(Node **Head)
        {
            Node **temp;

            while (*Head) {
                temp = &(*Head)->next;
                free (*Head);
                Head = temp;
            }
        }

Now this looks a little complicated with all these doubly indirect pointers.
It's better to just write the whole thing as:

        void DestroyList(Node **Head)
        {
            Node *temp, *victim = *Head;

            while (victim) {
                temp = victim->next;
                free(victim);
                victim = temp;
            }
        }

This way, you never have to worry about the value of the pointer that
was freed, because you never look at it again.

Is it important that after DestroyList, *Head is null? Without knowing
more about your list implementation, I can't tell, but you can always
add a

        *Head = 0;

as the last line of the above function.



Mon, 31 Jul 2000 03:00:00 GMT  
 Destroying All Nodes in a Linked List

Quote:
>Is it important that after DestroyList, *Head is null? Without knowing
>more about your list implementation, I can't tell, but you can always
>add a

> *Head = 0;

>as the last line of the above function.

I didn't want to paste all of the code to the news group, but if it would
help clarify what I'm doing then here it is (pasted at the bottom of the
message).  All I am doing is creating a linked list of integers, displaying
that list, destroying the list, then trying to display it again (but it
shouldn't display the second time because it's empty and therefore it will
print an appropriate message).  My question is the following:  Is my
DestroyList correct?  I ask because of the following:

(1) If I don't include the line *Head=NULL; (it's marked in the code as
"Line in Question") then when I try to print this list after destroying it
then it does actually print the list again.

(2) My concern is that I am not returning the memory to the heap properly
and that the list is considered "empty" only because I am assigning the
pointers to NULL.

Help is appreciated,

Derek Battams (** CODE FOLLOWS **)

#include <stdio.h>
#include <stdlib.h>
#define StringSize 255

typedef struct NodeTag
{
   int AnInt;
   struct NodeTag *Next;

Quote:
} Node;

void AddNodeToList (Node **, int);
void DisplayList (Node *);
void DestroyList (Node **);

void AddNodeToList (Node **Head, int Number)
{
Node *Current, *NewNode;
   NewNode = malloc (sizeof(Node));
   NewNode->AnInt = Number;
   NewNode->Next = NULL;
   if (*Head == NULL)
   {
      *Head = NewNode;
   }
   else
   {
      Current = *Head;
      while (Current->Next != NULL)
         Current = Current->Next;
      Current->Next = NewNode;
   }
   return;

Quote:
}

void DisplayList (Node *Head)
{
Node *Current;
   if (Head != NULL)
   {
      Current = Head;
      while (Current != NULL)
      {
         printf ("%d\n", Current->AnInt);
         Current = Current->Next;
      }
      printf ("Done displaying...\n");
   }
   else
      printf ("Nothing to display, this list is empty!\n");
   return;

Quote:
}

void DestroyList (Node **Head)
{
   if ((*Head)->Next != NULL)
      DestroyList (&((*Head)->Next));
   free (*Head);
   *Head = NULL; /* Line in question */
   return;

Quote:
}

int main ()
{
char *String;
Node *Head;
int *Number;

  Head = NULL;
  String = malloc (sizeof(char) * StringSize);
  Number = malloc (sizeof(int));
  fgets (String, StringSize, stdin);
  sscanf (String, "%d", Number);
  while (*Number != 0)
  {
     AddNodeToList (&Head, *Number);
     fgets (String, StringSize, stdin);
     sscanf (String, "%d", Number);
  }
  printf ("\nHere are the numbers that you typed...\n");
  DisplayList (Head);
  if (Head != NULL)
     DestroyList (&Head);
  DisplayList (Head);
  free (String);
  free (Number);
  return 0;

Quote:
}



Mon, 31 Jul 2000 03:00:00 GMT  
 Destroying All Nodes in a Linked List

: >Is it important that after DestroyList, *Head is null? Without knowing
: >more about your list implementation, I can't tell, but you can always
: >add a
: >
: > *Head = 0;
: >
: >as the last line of the above function.

: I didn't want to paste all of the code to the news group, but if it would
: help clarify what I'm doing then here it is (pasted at the bottom of the
: message).  All I am doing is creating a linked list of integers, displaying
: that list, destroying the list, then trying to display it again (but it
: shouldn't display the second time because it's empty and therefore it will
: print an appropriate message).  My question is the following:  Is my
: DestroyList correct?  I ask because of the following:

: (1) If I don't include the line *Head=NULL; (it's marked in the code as
: "Line in Question") then when I try to print this list after destroying it
: then it does actually print the list again.

: (2) My concern is that I am not returning the memory to the heap properly
: and that the list is considered "empty" only because I am assigning the
: pointers to NULL.

No, the malloc's and free's are balanced, and the code looks ok.  But
you are using the pointer you have set to null as a flag, to say 'no
more data here', and if you don't set this flag then the print statement
follows down the chain.  This is quite reasonable, but freeing memory
(on most OSes) doesn't explicitly clear it, so if you don't null the
pointer, and then access the memory it points to soon after the memory
has been de-allocated, you may well find that your data is still there.

This sort of access is illegal by any standard, and when done inadvertently
can be a major source of bugs, but it is (unfortunately) possible.  It's
a good reason for explicitly setting pointers to null when you free the
associated memory.

Will



Tue, 01 Aug 2000 03:00:00 GMT  
 Destroying All Nodes in a Linked List



Quote:
><HTML>

><BLOCKQUOTE TYPE=CITE>void AddNodeToList (Node **Head, int Number)</BLOCKQUOTE>
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Why to use Node **Head and call the
>function like this:
><BLOCKQUOTE TYPE=CITE>&nbsp;&nbsp;&nbsp;&nbsp; AddNodeToList (&amp;Head,
>*Number);</BLOCKQUOTE>
>instead of using:

Your article is unreadable. Try turning off HTML formatting in your
newsreader.

-----------------------------------------


-----------------------------------------



Wed, 16 Aug 2000 03:00:00 GMT  
 
 [ 7 post ] 

 Relevant Pages 

1. Destroying All Nodes is a Linked List

2. nodes linked listed and such

3. 2 nodes end up in a cycle in a single linked list

4. newbie question: removal of node in linked list

5. How to find a node in link list

6. Realloc()ing data of a node from a linked list

7. why malloc for a new node in linked list

8. Removing node from linked list

9. Removing a NODE for good (double linked lists)

10. deleting a previous node in a singly linked list

11. Question about swapping nodes in a doubly linked list

12. Deleting a node in a linked list

 

 
Powered by phpBB® Forum Software