not able to free memory

S

subirs

Hi,

I am facing problem in freeing memory in the following sample code.
---------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>


int main( int argc, char **argv)
{

int i;

typedef struct
{
double *Rho;
} Packet1;


Packet1 packet;
packet.Rho=(double *)malloc(3*sizeof(double));

for(i=0;i<3;i++)
packet.Rho=0.0;

for(i=0;i<3;i++)
{
packet.Rho=i;
printf("packet.Rho[%d]=%f \n",i,packet.Rho);
}

free(packet.Rho);
if(packet.Rho != NULL)
printf("memory not freed \n");


return 0;
}

------------------------------------------------------------------------------
Output of the code says memory not freed. What should I do to free the
memory ? Another limitation is that I cannot use a pointer to the
structure as I need to use the above format of program in a parallel
code which is needed to be passed from one processor to another.

Any help will be deeply appreciated.
regards,

Subir
 
M

Martin Ambuhl

subirs said:
Hi,

I am facing problem in freeing memory in the following sample code.

No, you have a problem in thinking that you can tell whether memory was
freed with your test.
Not only is said:
int main( int argc, char **argv)
{

int i;

typedef struct
{
double *Rho;
} Packet1;

Some people doubt the wisdom of using a typedef here, but your mileago
probalby varies. Not a big deal one way or the other.
Packet1 packet;
packet.Rho=(double *)malloc(3*sizeof(double));

The cast of the return of malloc is a poor practice when programming in
C, although at least one language based on C and designed to make highly
obfuscated code the norm requires it.

Worse, though, is the explict type used with sizeof. There are several
good reasons to prefer
packet.Rho = malloc(3 * sizeof *packet.Rho);
for(i=0;i<3;i++)
packet.Rho=0.0;

for(i=0;i<3;i++)
{
packet.Rho=i;
printf("packet.Rho[%d]=%f \n",i,packet.Rho);
}

free(packet.Rho);
if(packet.Rho != NULL)
printf("memory not freed \n");


return 0;
}


It could be anything. free() does not set the pointer to NULL, so
testing for that tells you nothing.
What should I do to free the
memory ?

What you did.
 
K

Keith Thompson

subirs said:
I am facing problem in freeing memory in the following sample code.

<malloc.h> is not a standard header. malloc() and free() are declared
in said:
int main( int argc, char **argv)
{

int i;

typedef struct
{
double *Rho;
} Packet1;


Packet1 packet;
packet.Rho=(double *)malloc(3*sizeof(double));

Don't cast the result of mallo(). A better way to write this is:

packet.Rho = malloc(3 * sizeof *packet.Rho);
for(i=0;i<3;i++)
packet.Rho=0.0;

for(i=0;i<3;i++)
{
packet.Rho=i;
printf("packet.Rho[%d]=%f \n",i,packet.Rho);
}

free(packet.Rho);
if(packet.Rho != NULL)
printf("memory not freed \n");


return 0;
}

[...]

No, it doesn't. free() doesn't set its argument to NULL -- in fact,
since the argument is passed by value, it *can't*.

When you pass a pointer to free(), the memory is deallocated; there's
no indication of whether the deallocation was successful. Even
referring to the value of the pointer after it's been free()d.
 
N

Nick Keighley

subirs wrote:

<snip>

I've tidied the layout of ht code. Don't use tabs in posted code.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>


int main( int argc, char **argv)
{

int i;

typedef struct
{
double *Rho;
} Packet1;

Packet1 packet;
packet.Rho = (double *)malloc(3*sizeof(double));

for (i=0;i<3;i++)
packet.Rho=0.0;

for (i=0; i<3; i++)
{
packet.Rho=i;
printf("packet.Rho[%d]=%f \n",i,packet.Rho);
}

free(packet.Rho);
if(packet.Rho != NULL)
printf("memory not freed \n");

return 0;
}

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

Another limitation is that I cannot use a pointer to the
structure as I need to use the above format of program in a parallel
code which is needed to be passed from one processor to another.


I don't get this. Are you trying to pass a pointer to a structure from
one processor to another? You'll need to transfer the contents of the
structure to a new structure in the other processor. If I've
misunderstood
please give more detail.
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

subirs said:
Hi,

I am facing problem in freeing memory in the following sample code.
---------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>


int main( int argc, char **argv)
{

int i;

typedef struct
{
double *Rho;
} Packet1;


Packet1 packet;
packet.Rho=(double *)malloc(3*sizeof(double));

for(i=0;i<3;i++)
packet.Rho=0.0;

for(i=0;i<3;i++)
{
packet.Rho=i;
printf("packet.Rho[%d]=%f \n",i,packet.Rho);
}

free(packet.Rho);
if(packet.Rho != NULL)
printf("memory not freed \n");


return 0;
}

------------------------------------------------------------------------------
Output of the code says memory not freed. What should I do to free the
memory ? Another limitation is that I cannot use a pointer to the
structure as I need to use the above format of program in a parallel
code which is needed to be passed from one processor to another.


You are assuming free sets the pointer it frees to NULL.
This assumption is wrong.
 
S

subirs

Hi,

Thanks for replying to my quer.
Ok I have understodd the fallacy in my logic. I should never assume
that using "free" returns the pointer to NULL. But the main reason
which prompted to me to post this code and ask is that this type of the
code( it has more malocs etc.) is used in a function which is called
hundred of times in each iterations and there are thousands of
iterations. So while using "TOP" to monitor my code I found that
code+data=stack size under SIZE increases quite rapidly and this cuases
my rpogram to die out after sometime if I go for higher number of
iterations.

So what should I do to control the stack size ( as i feel beacuse of
this type of code in the function my stack size is increasing).

Is there anyway by which I can be dead sure that the memory is freed
(which I now feel it does) and my stack size does not increase due to
the code.

Subir
 
I

Ian Malone

subirs said:
Hi,

Thanks for replying to my quer.
Ok I have understodd the fallacy in my logic. I should never assume
that using "free" returns the pointer to NULL. But the main reason
which prompted to me to post this code and ask is that this type of the
code( it has more malocs etc.) is used in a function which is called
hundred of times in each iterations and there are thousands of
iterations. So while using "TOP" to monitor my code I found that
code+data=stack size under SIZE increases quite rapidly and this cuases
my rpogram to die out after sometime if I go for higher number of
iterations.

So what should I do to control the stack size ( as i feel beacuse of
this type of code in the function my stack size is increasing).

Is there anyway by which I can be dead sure that the memory is freed
(which I now feel it does) and my stack size does not increase due to
the code.

There are a couple of misunderstandings here:
free frees a pointer returned by malloc, this is guaranteed. As far as
your program is concerned it's freed, however your implementation might
not return the memory to the rest of the system immediately.
If the amount of memory your program uses keeps going up until it
crashes then you've forgotten to free an allocated pointer somewhere.

Second, "return value" I think you've misunderstood what this means.
In your posted code you have:
packet.Rho = (double *)malloc(3*sizeof(double));

Malloc returns a value (void *), which is cast to a pointer to double
(others have mentioned this isn't best practice), and then packet.Rho
is set equal to that value. The return value is what results from
evaluating malloc(), and for a C function it results from the return
statement in a function. In your post you say, "I should never assume
that using "free" returns the pointer to NULL." In fact free has type
void and doesn't return /anything/. It has an argument of type void *,
this is not a return value. It can't do anything to that argument
either: arguments in C are passed by value, try and find the classic
case of swapping the values of two variables using a function. This
is one of the uses of pointers.

eg (without prototypes)

int a;
int *b = &a;
functiona(a); /* Gets given value of a, can't change a in the calling
* function */
functionb(b); /* Gets given value of b, can't change b in the calling
* function, but can use the pointer to change the
* value of the object it points to (a) */
functionb(&a);/* Directly given the lvalue &a, the address of a, so can
* modify a; but it's not a that has been passed, it's
* a pointer to a, as in functionb(b) */

Finally, your example uses the return value of malloc without checking
it. If the memory can't be allocated malloc will return NULL, you
should check if(!packet.Rho) (equivalent to if(packet.Rho == NULL))
before using it. (There's a similar case for realloc, it will return
NULL if it can't change the amount of allocated memory, but the
existing data will be unchanged and not freed, so you need use a
temporary pointer to hold and test the result of realloc. It can also
move the memory block if successful, in which case you have to change
your pointer to the one returned by realloc).
 
F

Fred Kleinschmidt

Ian Malone said:
There are a couple of misunderstandings here:
free frees a pointer returned by malloc, this is guaranteed. As far as
your program is concerned it's freed, however your implementation might
not return the memory to the rest of the system immediately.
If the amount of memory your program uses keeps going up until it
crashes then you've forgotten to free an allocated pointer somewhere.

Second, "return value" I think you've misunderstood what this means.
In your posted code you have:
packet.Rho = (double *)malloc(3*sizeof(double));

Malloc returns a value (void *), which is cast to a pointer to double
(others have mentioned this isn't best practice), and then packet.Rho
is set equal to that value. The return value is what results from
evaluating malloc(), and for a C function it results from the return
statement in a function. In your post you say, "I should never assume
that using "free" returns the pointer to NULL." In fact free has type
void and doesn't return /anything/. It has an argument of type void *,
this is not a return value. It can't do anything to that argument
either: arguments in C are passed by value, try and find the classic
case of swapping the values of two variables using a function. This
is one of the uses of pointers.
I think the OP was not referring to the value returned by free,
but was using the phrase "returns the pointer to NULL" to mean
"resets the pointer passed to it to NULL", i.e., thinking that
maybe the value of the argument was reset to NULL,
which, as you pointed out, cannot be done.

I've always wondered a bit why free() was not written
to accept a pointer to the pointer, so that it COULD then
set it to NULL.
 
I

Ian Malone

I think the OP was not referring to the value returned by free,
but was using the phrase "returns the pointer to NULL" to mean
"resets the pointer passed to it to NULL", i.e., thinking that
maybe the value of the argument was reset to NULL,
which, as you pointed out, cannot be done.

Yes, I thought that's what they meant too, and that maybe they
were confused about argument passing vs. return values.
I've always wondered a bit why free() was not written
to accept a pointer to the pointer, so that it COULD then
set it to NULL.

It's simpler this way? There's no particular reason to set
it to NULL unless you're going to re-use it. That and the
less functions that modify their arguments[1] the clearer
the code is (though it's often unavoidable, eg strcpy).

[1] Objects pointed to by their arguments, just to avoid
further confusion.
 
D

Default User

Fred Kleinschmidt wrote:
I've always wondered a bit why free() was not written
to accept a pointer to the pointer, so that it COULD then
set it to NULL.

Casting every pointer you pass to free() would be rather annoying.
Besides, is it so hard to add an explicit set when it's needed?


Brian
 
K

Keith Thompson

Fred Kleinschmidt said:
I've always wondered a bit why free() was not written
to accept a pointer to the pointer, so that it COULD then
set it to NULL.

It would make the interface more complicated, and it wouldn't solve
the problem. Also, different pointer-to-pointer types are not
generally compatible.

void xfree(void **ptr);

int *p = malloc(sizeof (p);
int *q = p;
xfree((void**)&p); /* questionable cast */
/* p == NULL, but q is indeterminate */
 
S

subirs

Hi,

Could anyone tell me where I could find the use of malloc ( and other
aspects of c programming) like

packet.Rho = malloc(3 * sizeof *packet.Rho);--------(a)

instead of
packet.Rho=(double *)malloc(3*sizeof(double)); -------------(b)

I think most of the book mention (b). I would also like to know about
the advantages and other features of using C.

Regards,

Subir
 
V

Vladimir S. Oka

subirs said:

Please quote context. Alternatively, if you want to ask a new question
start a new thread.
Could anyone tell me where I could find the use of malloc ( and other
aspects of c programming) like

packet.Rho = malloc(3 * sizeof *packet.Rho);--------(a)

In well-written C code.
instead of
packet.Rho=(double *)malloc(3*sizeof(double)); -------------(b)

I think most of the book mention (b).

In which case they're shelling out bad advice.

Casting the return of `malloc()` will hide the error of not including
<stdlib.h>.

Using `sizeof` the object pointed to, rather than the `sizeof()` its
type provides for easier maintenance, as when the type of the object
changes, you don't need to change the `malloc()` call (i.e., line (a)
needs no modification regradless of the type used).
I would also like to know about
the advantages and other features of using C.

For that, your best bet is getting a *good* book on C. One could do
worse than Kernighan & Ritchie, The C Programming Language, Second
Edition.
 
R

Richard Bos

Fred Kleinschmidt said:
I've always wondered a bit why free() was not written
to accept a pointer to the pointer, so that it COULD then
set it to NULL.

For one, because that would make the interface unnecessarily
complicated. For another, it doesn't solve the problem, and lures
beginners into an unwarranted sense of security. Pointers can be copied,
so even when you set that one pointer to null after you free the memory,
there can still be copies floating around with invalid values in them.
With the null-after-free() trick, a seductive error is to assume that
any non-null pointer is guaranteed safe, and throw truly safe pointer
handling to the side.

Richard
 
C

Chris Torek

I've always wondered a bit why free() was not written
to accept a pointer to the pointer, so that it COULD then
set it to NULL.

As others noted, this is not nearly as useful as it first
appears, because, e.g.:

void f(void) {
char *p1, *p2;
...
p1 = malloc(somesize);
if (somecond)
p2 = p1;
else
p2 = othervalue;
... /* code that does not change p1 or p2 */
free(p1);
p1 = NULL; /* now we're safe ... or are we? */

/* At this point, even though p1==NULL, p2 may be invalid. */
/* (Worse, it depends on what "somecond" was.) */
...
}

One could, of course, decree that the "safety" effect of
setting p1 to NULL exceeds the "lack of safety" effect of
the ability of the programmer to copy p1 to p2, and therefore
one's free()-like function would in fact set the pointer to
NULL every time, forcing the programmer to pass the address
of the pointer variable. But this makes *using* the thing
difficult. Let us suppose that my_malloc() hands out
"double *"s and "my_free()" revokes "double *"s:

double *my_malloc(size_t n) {
return malloc(n * sizeof(double));
}

void my_free(double *dp) {
free(*dp);
*dp = NULL;
}

Clearly we can use these to allocate and free space for "double"s:

void g(void) {
double *dp;
...
dp = my_malloc(some_n);
if (dp == NULL) ... handle error ...
... now we can use dp where 0 <= i < n ...
my_free(&dp);
/* now dp == NULL */
}

Alas, we cannot use this for any other type, only for "double",
because my_free() sets a "double *". If we try to generalize it
a la malloc(), using "void *", we have a problem:

void *my_malloc(size_t size) {
return malloc(size);
}

void my_free(void **vp) {
free(*vp);
*vp = NULL;
}

Now the only *correct* call to my_free() passes the address of an
actual "void *" object. So we might rewrite g(), which needs
"double"s, thus:

void g(void) {
double *dp;
void *vp;
...
dp = my_malloc(some_n * sizeof *dp);
if (dp == NULL) ... handle error ...
... now we can use dp where 0 <= i < n ...
/* now it is time to free it so we must copy it to vp */
vp = dp;
my_free(&vp);
/* now vp == NULL, but most likely dp != NULL */
}

We have gained "safety" for vp, but we are not using vp except
for this one call. To copy the "safety effect" to dp we need
to include one more line of code in g():

... now we can use dp where 0 <= i < n ...
/* now it is time to free it so we must copy it to vp */
vp = dp;
my_free(&vp);
dp = vp;
/* now vp == NULL and dp == NULL; voila, safety! */

But we can do this just as well by writing:

vp = dp;
my_free(&vp);
dp = NULL; /* = NULL instead of = vp; it works the same */

and if we do this, it becomes obvious that having my_free() set
vp to NULL is useless: the caller can set the "real" variable
(in this case, dp) to NULL himself. So we can remove that line
from my_free(), making it read:

void my_free(void **vp) { free(*vp); }

which needlessly requires the address of a "void *" variable,
so we can simplify it further to:

void my_free_2(void *vp) { free(vp); }

but now my_malloc() is just plain old malloc(), and my_free_2()
is just plain old free().

This, then, is the rest of the reason why free() does not bother
to attempt to set the caller's variable(s) to NULL: it does not
know, and should not need to know, the type(s) of its caller's
variable(s), or how many of them need to be NULL-ed out. The
caller knows those things, and can do it just as easily -- or
indeed, *more* easily, most often.
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top