free'ing malloc'd structure with malloc'd members

J

John

In the course of an assignment, I learned the hard way that I shouldn't try
to free a malloc'd member of a malloc'd structure after having freed that
structure (i.e., free( structure ); free( structure->bufferspace ) ).

My question is, if I free just the structure, will the (e.g.) bufferspace be
freed implicitly, or do I have to (as I currently am) free the members
first?

Thanks.
-cjl
 
M

Martin Ambuhl

John said:
In the course of an assignment, I learned the hard way that I shouldn't try
to free a malloc'd member of a malloc'd structure after having freed that
structure (i.e., free( structure ); free( structure->bufferspace ) ).

My question is, if I free just the structure, will the (e.g.) bufferspace be
freed implicitly, or do I have to (as I currently am) free the members
first?

Free the members first. Information about subsequent allocation of
members is not magically incoded into the information about the
structure allocation.
 
E

Emmanuel Delahaye

John wrote on 30/07/04 :
In the course of an assignment, I learned the hard way that I shouldn't try
to free a malloc'd member of a malloc'd structure after having freed that
structure (i.e., free( structure ); free( structure->bufferspace ) ).

My question is, if I free just the structure, will the (e.g.) bufferspace be
freed implicitly, or do I have to (as I currently am) free the members
first?

"All what have been done must be undone".

IOW, yes, you have to free the innermost elements first. There is no
implicit automatic mecanism that frees the memory in C.

That said, you can write a pair of function known as 'creator /
destructor' that helps to create / delete the objects properly and hide
some gory details the user is not supposed to deal with.

myobj_s *myobj_create (void);
void myobj_delete (myobj_s *this);
 
W

Wayne Rasmussen

Martin said:
Free the members first. Information about subsequent allocation of
members is not magically incoded into the information about the
structure allocation.

Ah, but what if some other structure is also pointing to one of those members? Do
you keep a count of the number of items pointing to that member, and decrement
when you might free it until it reaches 0, then free it?...
 
M

Malcolm

Wayne Rasmussen said:
Ah, but what if some other structure is also pointing to one of those
members? Do you keep a count of the number of items pointing to that
member, and decrement when you might free it until it reaches 0, then free
it?...
You've got to be disciplined. The general rule is that only one pointer
should exist in long-term storage (obviously you must take copies to pass to
subroutines, or for local manipulations).
With some data structures, like linked lists, this isn't possible.
Inherently there are two pointers to each node of a doubly-linked list. So
you must define an object as "my doubly linked list data structure" and then
write functions which will manipulate it, and especially destroy it, in a
controlled way. Once the list is destroyed, all the pointers to data nodes
should go with it.
 
A

Alan Balmer

Ah, but what if some other structure is also pointing to one of those members? Do
you keep a count of the number of items pointing to that member, and decrement
when you might free it until it reaches 0, then free it?...
Well, first you review your design, because there is probably a better
way to do it ;-)

But if you must, yes, reference counters are a common way to handle
the situation.
 
W

Wayne Rasmussen

Alan said:
Well, first you review your design, because there is probably a better
way to do it ;-)

But if you must, yes, reference counters are a common way to handle
the situation.

Sure, good design should be done first. But this is more of the what if variety.
Actually, was curious to see other ways people might deal with this. Other than good
design, what would be the other common ways? Having a master array of that type for
example.

Not looking to create a garage collector either!


cya,
wayne
 
W

Wayne Rasmussen

Malcolm said:
You've got to be disciplined. The general rule is that only one pointer
should exist in long-term storage (obviously you must take copies to pass to
subroutines, or for local manipulations).
With some data structures, like linked lists, this isn't possible.
Inherently there are two pointers to each node of a doubly-linked list. So
you must define an object as "my doubly linked list data structure" and then
write functions which will manipulate it, and especially destroy it, in a
controlled way. Once the list is destroyed, all the pointers to data nodes
should go with it.

Well, doubly linked lists are a special case for sure.

I was trying to think of a good example, like say a chess board where you would
want to try some search with alpha-beta and backtracking. But in those cases,
you really should be making copies of game board and everything it refers to or
at least, have a way to get back to the previous position when backtracking.

Then I was thinking of a DB, where you might have different links say to a
zipcode table record, but ideally there should be one path to get to that
information should there?

If you were doing your own garbage collector you might have to worry about this.
 
K

Karthik

John said:
In the course of an assignment, I learned the hard way that I shouldn't try
to free a malloc'd member of a malloc'd structure after having freed that
structure (i.e., free( structure ); free( structure->bufferspace ) ).

My question is, if I free just the structure, will the (e.g.) bufferspace be
freed implicitly, or do I have to (as I currently am) free the members
first?

huh, if only that was true (freeing members implicitly), there
would be less memory leaks on earth. Unfortunately it is not true.

You got two problems:-
smaller one: your memory access is likely to cause seg. fault ( you are
going out of the address space of the process).

bigger one: memory leak.

Pointer is nothing but a variable that stores an address. The
moment you do a free(structure), the memory pointed to by that address
is reclaimed by the GC ( in other words, that could be used again by the
memory manager in the future). But the info. to delete
sturucture->bufferspace has already been freed by your previous
statement. So you won't find the address that ought to be removed as far
as 'structure->bufferspace' is concerned.


Try to group the malloc/free in a function as far as possible. It
would help you to get rid of memory leaks ( and anyone who had to
read/maintain would be thankful to you for that).

HTH.

- Karthik.
 
S

Stan Milam

Wayne said:
Martin Ambuhl wrote:




Ah, but what if some other structure is also pointing to one of those members? Do
you keep a count of the number of items pointing to that member, and decrement
when you might free it until it reaches 0, then free it?...


In my humble opinion having foriegn structure members point to other
structure members is just bad programming design. Loose coupling and
tight cohesiveness is not only desirable for coded functions, but for
data too. As to the issue of freeing malloc'd members I would suggest,
at the very least, to have a dedicated function to free all the members,
then free the structure last of all.

Regards,
Stan Milam.
 
F

Flash Gordon

Alan Balmer wrote:


Sure, good design should be done first. But this is more of the what
if variety. Actually, was curious to see other ways people might deal
with this. Other than good design, what would be the other common
ways? Having a master array of that type for example.

Not looking to create a garage collector either!

The best way of dealing with this depends on the problem being solved
and the design of the SW, so the only way to handle it reliably is with
good SW design. IMHO any other method leads to bugs and/or madness.

In general you need some easily determined relationship between the
point at which the space is allocated, when it is used and when it is
freed. Normally I go for a single pointer to either the data or to the
root of a tree or list of some form. Sometimes I would consider a
reference counter, but not very often. Always when it is a complex
situation (reference counts, linked lists, trees etc.) use a library to
maintain the structure and have a single master record (e.g. the pointer
to the root of a tree).
 
M

Malcolm

Stan Milam said:
In my humble opinion having foriegn structure members point to other
structure members is just bad programming design. Loose coupling and
tight cohesiveness is not only desirable for coded functions, but for
data too. As to the issue of freeing malloc'd members I would suggest,
at the very least, to have a dedicated function to free all the members,
then free the structure last of all.
You're right, but the problem is that the ideal design isn't always easy to
come up with.
Let's say we have a video game with rats running about a maze. You will need
a structure for each cell of the maze, with a pointer to the rats. However
it is also very handy to have a list of rats, without iterating over every
cell of the maze, and each rat probably needs a pointer to the cell of the
maze that it is in. So we end up with a non-ideal situation of several
pointers in different structures pointing to the same thing.
 
D

Dag Viken

John said:
In the course of an assignment, I learned the hard way that I shouldn't try
to free a malloc'd member of a malloc'd structure after having freed that
structure (i.e., free( structure ); free( structure->bufferspace ) ).

My question is, if I free just the structure, will the (e.g.) bufferspace be
freed implicitly, or do I have to (as I currently am) free the members
first?

Thanks.
-cjl
Yes, free() any members that have been malloc()'ed first.
This is why C++ has destructors!
 
P

pete

John said:
In the course of an assignment, I learned the hard way that I shouldn't try
to free a malloc'd member of a malloc'd structure after having freed that
structure (i.e., free( structure ); free( structure->bufferspace ) ).

My question is, if I free just the structure,
will the (e.g.) bufferspace be freed implicitly,

It will not be freed implicitly.
or do I have to (as I currently am) free the members first?

Sometimes you don't want to.
You might have lists of lists.
Say for example, a list of people's characteristics in nodes,
and each person node has a list of some friend's names.
If you have John Smith with a friend's name in one list
and the same John Smith with two friends' names in another list,
Then you might want to combine the two lists of people's
characteristics in such a way that the two lists of friends'
names are combined into one list on the first John Smith node
while the second John Smtih node is freed,
leaving it's member list attached to the first John Smith node.

When the time comes to free the big list, though,
the member lists will need to be freed first.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,263
Messages
2,571,062
Members
48,769
Latest member
Clifft

Latest Threads

Top