memory allocation and freeing memory

R

Rodrigo Dominguez

there are sometimes that I use third party libraries, I use some functions
that returns char * or structs, etc. sometimes the memory that is returned
by those libraries, when I try to free this memory whith the function free,
it brokes my application, and sometimes it's ok, why? how do I realize when
I have to free the memory that is allocated by third party libraries and
why sometimes I don't have to free this memory?

Thank you
 
R

Robert Gamble

Rodrigo said:
there are sometimes that I use third party libraries, I use some functions
that returns char * or structs, etc. sometimes the memory that is returned
by those libraries, when I try to free this memory whith the function free,
it brokes my application, and sometimes it's ok, why? how do I realize when
I have to free the memory that is allocated by third party libraries and
why sometimes I don't have to free this memory?

You need to read the documentation that came with the libraries. The
functions that allocate memory should either have cleanup functions
that do deallocation or specify how you should free the objects
yourself.

Robert Gamble
 
E

Emmanuel Delahaye

Rodrigo Dominguez wrote on 13/06/05 :
there are sometimes that I use third party libraries, I use some functions
that returns char * or structs, etc. sometimes the memory that is returned
by those libraries, when I try to free this memory whith the function free,
it brokes my application, and sometimes it's ok, why? how do I realize when

Don't do that. Read the manual and follow the instructions.
I have to free the memory that is allocated by third party libraries and
why sometimes I don't have to free this memory?

There are several ways to implement a function returning a pointer to
an object. Only the library documentation informs you about the proper
way of using the functions.

I personally tend to add a '_dyn' suffix to functions returning
something to be freed to make it self-documenting...

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"There are 10 types of people in the world today;
those that understand binary, and those that dont."
 
J

Jean-Claude Arbaut

I personally tend to add a '_dyn' suffix to functions returning
something to be freed to make it self-documenting...

A good practice (I think, I'm not a guru): a function never
returns a block it has allocated. This means that the caller
never frees memory, and the callee always frees all its
allocated blocks before function returns. If the callee needs
to return a block, then the caller allocates it and pass it
as an argument. Maybe there are situations where it doesn't work ?
 
K

Keith Thompson

Jean-Claude Arbaut said:
A good practice (I think, I'm not a guru): a function never
returns a block it has allocated. This means that the caller
never frees memory, and the callee always frees all its
allocated blocks before function returns. If the callee needs
to return a block, then the caller allocates it and pass it
as an argument. Maybe there are situations where it doesn't work ?

That approach is often useful, but it requires the caller to decide
how big a block to allocate (and pass the actual size as another
argument). If the caller allocates too little memory, the call fails;
if the caller allocates too much, the extra space is wasted. Leaving
the allocation up to the function allows the function to allocate
exactly as much space as is needed. On the other hand, it means the
caller has the burden of freeing it.
 
E

Eric Sosman

Jean-Claude Arbaut said:
A good practice (I think, I'm not a guru): a function never
returns a block it has allocated. This means that the caller
never frees memory, and the callee always frees all its
allocated blocks before function returns. If the callee needs
to return a block, then the caller allocates it and pass it
as an argument. Maybe there are situations where it doesn't work ?

An approach I've found useful is to write pairs of
functions: one function allocates and initializes memory
for a Whatever and returns a Whatever*, while the other
accepts a Whatever* argument and does whatever is needed
to "de-initialize" the Whatever, including releasing its
memory. The advantage is that the caller never needs to
the details of how a Whatever is built: how much memory
is needed, whether it's all in one chunk or is built from
several pieces linked together, and so on.

For example, consider fopen() and fclose(). As the
caller you do not need to know anything about what a `FILE'
looks like; all you care about is the `FILE*'. You do not
know whether the `FILE' is allocated dynamically or statically,
what extra buffers and such may be allocated along with it,
and so on -- all you need to know is that fopen() produces a
`FILE*', and that fopen() cleans it up when you're done.

The same pattern works well for "purely memory" constructs,
too. I've written a little expression evaluator that has
three (principal) functions in its interface: a compiler that
transforms the source expression into an "opaque" data type
that's allocated during compilation, an evaluator that takes
the opaque pointer and an array of user-supplied variable
values and returns the expression's value, and a destructor
that accepts the opaque pointer and discards the memory it
uses. The current version of the destructor is fairly simple:

void ExprDestroy(Expr *expr) {
free (expr);
}

.... but by packaging it where the caller can't see the details
I retain the freedom to change my mind about the way memory is
managed, and perhaps do something like

void ExprDestroy(Expr *expr) {
free (expr->constants);
free (expr->bytecodes);
#ifndef NDEBUG
free (expr->debugging_info);
#endif
free (expr);
}

The caller never needs to know how things are done "behind the
curtain."
 
J

Jean-Claude Arbaut

Le 13/06/2005 23:22, dans (e-mail address removed), « Keith Thompson »
That approach is often useful, but it requires the caller to decide
how big a block to allocate (and pass the actual size as another
argument). If the caller allocates too little memory, the call fails;
if the caller allocates too much, the extra space is wasted. Leaving
the allocation up to the function allows the function to allocate
exactly as much space as is needed. On the other hand, it means the
caller has the burden of freeing it.

Often the caller knows the size, or a bound may be known, and written in the
documentation. If the size is unknown a priori, maybe a first call can
compute a bound, and return the size. But there are cases when you simply
don't know the size before the computation, you're right.

In these situations, I would suggest a malloc/free approach: the allocating
function has a freeing counterpart. That's what is used in fopen/fclose I
suppose. And it allows modifications in the implementation: if you free all
struct members yourself, you depend on the struct "structure" :)
 
J

Jean-Claude Arbaut

Le 13/06/2005 23:22, dans [email protected], « Eric
Sosman » said:
An approach I've found useful is to write pairs of
functions: one function allocates and initializes memory
for a Whatever and returns a Whatever*, while the other
accepts a Whatever* argument and does whatever is needed
to "de-initialize" the Whatever, including releasing its
memory. The advantage is that the caller never needs to
the details of how a Whatever is built: how much memory
is needed, whether it's all in one chunk or is built from
several pieces linked together, and so on.

For example, consider fopen() and fclose(). As the
caller you do not need to know anything about what a `FILE'
looks like; all you care about is the `FILE*'. You do not
know whether the `FILE' is allocated dynamically or statically,
what extra buffers and such may be allocated along with it,
and so on -- all you need to know is that fopen() produces a
`FILE*', and that fopen() cleans it up when you're done.

The same pattern works well for "purely memory" constructs,
too. I've written a little expression evaluator that has
three (principal) functions in its interface: a compiler that
transforms the source expression into an "opaque" data type
that's allocated during compilation, an evaluator that takes
the opaque pointer and an array of user-supplied variable
values and returns the expression's value, and a destructor
that accepts the opaque pointer and discards the memory it
uses. The current version of the destructor is fairly simple:

void ExprDestroy(Expr *expr) {
free (expr);
}

... but by packaging it where the caller can't see the details

I retain the freedom to change my mind about the way memory is
managed, and perhaps do something like

void ExprDestroy(Expr *expr) {
free (expr->constants);
free (expr->bytecodes);
#ifndef NDEBUG
free (expr->debugging_info);
#endif
free (expr);
}

The caller never needs to know how things are done "behind the
curtain."

Ok, I was late in my answer ;-)

Indeed, I have already used this approach, I wonder why I didn't
Remember that earlier... Shame on me !
 
E

Emmanuel Delahaye

Jean-Claude Arbaut wrote on 13/06/05 :
A good practice (I think, I'm not a guru): a function never
returns a block it has allocated. This means that the caller
never frees memory, and the callee always frees all its
allocated blocks before function returns. If the callee needs
to return a block, then the caller allocates it and pass it
as an argument. Maybe there are situations where it doesn't work ?

How would malloc() work in such a world ?

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
 
J

Jean-Claude Arbaut

Le 14/06/2005 21:30, dans (e-mail address removed),
« Emmanuel Delahaye » said:
Jean-Claude Arbaut wrote on 13/06/05 :
How would malloc() work in such a world ?

I'm not sure I understand your question. If you know how much space a
function will need, it isn't difficult to malloc and to pass it as a
parameter. No problem with malloc. But, maybe you mean that malloc
doesn't obey this precept ? That's right.

Anyway, Eric Sosman has already suggested a good solution for cases
when one doesn't know in advance how much space is needed.

Oh, and in case you hadn't noticed: what I describe is a method used
in many F77 programs to pass arrays. F77 cannot allocate memory, so
the usual trick is: create a big data chunk (a global variable), wide enough
for all your needs, merely a heap. Then treat this "heap" as a stack,
and pass variables in that stack to functions as needed (and maintain
stack state). It's the method used in PORT3 to emulate dynamic allocation.
Even in F90, there are programs that allocate memory at the beginning
of the program and use that trick afterwards, MT3D is an example.
 
E

Emmanuel Delahaye

Jean-Claude Arbaut wrote on 14/06/05 :
Oh, and in case you hadn't noticed: what I describe is a method used
in many F77 programs to pass arrays. F77 cannot allocate memory, so
the usual trick is: create a big data chunk (a global variable), wide enough
for all your needs, merely a heap. Then treat this "heap" as a stack,
and pass variables in that stack to functions as needed (and maintain
stack state).

Doesn't work on a mutithreaded environment...

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

..sig under repair
 
J

Jean-Claude Arbaut

Le 15/06/2005 01:28, dans (e-mail address removed),
« Emmanuel Delahaye » said:
Jean-Claude Arbaut wrote on 14/06/05 :

Doesn't work on a mutithreaded environment...

Yes, but it was a trick to bypass F77 lack of dynamic allocation... No
threads there. But maybe you can hack F77 to make use of threads, I
really don't know, and that's another story. And if you try that in C with
malloc, it should be thread-friendly, after all you pass your variables to
functions, that's all !
 

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
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top