Newsgroups: comp.lang.c
From: wkaufman@us.oracle.com (William Kaufman)
Subject: Re: How does free() work ?
Organization: Oracle Corporation, Redwood Shores CA
Date: Tue, 13 Oct 1992 03:18:13 GMT
X-Disclaimer: This message was written by an unauthenticated user
              at Oracle Corporation.  The opinions expressed are those
              of the user and not necessarily those of Oracle.

In article <1992Oct12.182006.3996@darwin.ntu.edu.au> cjw@dme.nt.gov.au writes:
] I am just curious about the function of free(). If
] I have a linked list and I free the head of it ie.
] 
] free(first_name) ;
] 
] where name contains further linked lists called
] say, male_friends & female_friends, does free() then 
] de-allocate their memory as well ?

    Nope.  All malloc() knows is, "give him a chunk of memory"; all
free() knows is "free up a chunk of memory".  Neither "knows" that the
chunk contains pointers.

    And notice that, if free() did free pointed-at pointers, it might
cause problems elsewhere.  If you've got something like:

        struct foo { struct foo *next; int data; } *a, *b;

then you malloc() an a and a b and set a->next = b, you'd have to unset
a->next if you wanted to free a.

] Or is it necessary
] to do something like the following :
] 
] free(first_name->first_male_friends) ;
] free(first_name->first_female_friends) ;
] free(first_name) ;

    Yes, that'll work, as long as the first_[fe]male_friend don't have
any pointers that will need freeing; and those pointers don't have
pointers; and those pointers,...  The usual way to do this if you've got
a hierarchical tree (i.e., I'm never a friend of my friend or her
friends) is to walk the tree recursively:

        void free_name(name *first_name)
        {
            if (first_name != (name *)NULL)
            {
              free_name(first_name->first_male_friends);
              free_name(first_name->first_female_friends);
              free((void *)first_name);
            }
        }

    Unfortunately, if there's some loop in the network, you could end up
freeing a pointer twice, which is a Bad Thing (crashes on most system).
In this case, you'll have to do some trick like:

    - remember how many times you linked it; when you've deleted the
      node (and decremented the count) enough times that the count is
      zero, *really* free it.
    - when you delete a node, walk through the whole network first and
      remove every mention of it.

    (If your example is any clue, though, you're going to have a ton of
problems like this.  If a's first friend is b, how do you know who a's
second friend is?  If c's first friend is also b, what about c's second
friend (who isn't the same as a's)?  Hopefully, you've already dealt
with this kind of thing,...)

] This is not especially crucial on my machine, but will be 
] for the end users I suspect. 

    Could be.  Depends on how much data there is (i.e., how much memory
your program will eat).  Also, be aware that there are systems which do
*not* free memory automatically when your program exits: if you don't
free the memory, the machine runs out and will have to be rebooted.

                                           -- Bill K.

Bill Kaufman,          | "...all conscious species are plastic and
Corporate Lackey       |  all plastic species are conscious."
wkaufman@us.oracle.com |                     -- Yew-Kwang Ng
Newsgroups: comp.lang.c