|
Home > Archive > Unix Programming > May 2006 > freeing memory
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| bofh1234@hotmail.com 2006-05-08, 7:15 pm |
| I have this client server program that with some (alright alot ) of
help from the community I have working great now. I want to make sure
I am freeing the memory properly. I am pretty sure I have to
free(Table1->ptr) because I do a malloc to get memory for it, but when
I put a free(Table1->ptr) before the free(whole struct) statement I get
a backtrace. So do I have to free my ptr, or will doing a free(whole
struct) be very nice and free all memory including the ptr?
Thanks,
Justin
I have the following struct:
structTable1 {
int vartype;
char varname[32];
void *ptr;
struct Table1 *next;
};
struct Table1 *Table1ptr=NULL, *temp;
I allocate Table1->ptr like this:
temp->ptr = malloc(sizeof(float));
My deletevarible function:
void delvarible(int fd, struct Table1 *sptr)
{
int n, size;
char *delpack;
struct Table1 *hold, *hold2=NULL;
readdelpacket.requesttype = 4;
delpack = (char*)(&delpacket) + sizeofint;
size = sizeof(delpacket) - sizeofint;
while ((n=read(fd, (void*)delpack, size)) >0){
size-=n;
delpack+=n;
}
size = 0;
hold = sptr;
while (hold != NULL) {
if (strcmp(delpacket.varname, hold->varname) == 0) {
if (hold2 == NULL) {
sptr = hold->next;
free(hold);
size = 1;
break;
}
else {
hold2->next = hold->next;
// free(hold->ptr); causes backtrace
free(hold);
size = 1;
break;
}
}
hold2 = hold;
hold = hold->next;
}
}
Finally the free all memory function:
void freelist(struct DSMTable *sptr)
{
struct DSMTable *temp;
while (sptr != NULL) {
temp = sptr->next;
free(sptr);
sptr = temp;
}
}
| |
| davids@webmaster.com 2006-05-08, 7:15 pm |
| There are a lot of problems in your code. However, the answer to your
specific question:
>do I have to free my ptr, or will doing a free(whole
>struct) be very nice and free all memory including the ptr?
Yes, you do. If the call to 'free' freed anything other than the
specific block you asked it to free, it would be a complete disaster.
(What if there's another pointer to that other chunk of memory?)
DS
| |
| Ralf Fassel 2006-05-09, 7:18 am |
| * bofh1234@hotmail.com
| So do I have to free my ptr, or will doing a free(whole struct) be
| very nice and free all memory including the ptr?
You need one free() for every malloc(), and the free()s need to be in
reverse order compared to the malloc()s (you first malloc() the
struct, then the pointer in the struct, but you first free() the
pointer in the struct, then the struct itself).
So yes, you need to free() the ptr before free()ing the struct.
Just free()ing the struct will not free() the ptr.
R'
| |
| bofh1234@hotmail.com 2006-05-09, 1:17 pm |
| I agree with both posts. For every malloc there must be a free. The
problem I have is that when I try to free (temp->ptr) I get a
backtrace. What am I doing wrong?
Thanks,
| |
| Ralf Fassel 2006-05-09, 1:17 pm |
| * bofh1234@hotmail.com
| The problem I have is that when I try to free (temp->ptr) I get a
| backtrace. What am I doing wrong?
Use a debugger and find out. Things to check are that temp->ptr
- is non-NULL when you try to free() it
- was actually allocated by a call to malloc before
- has not been changed in the meantime
If you're on Linux, you can also try valgrind.
http://valgrind.org/
R'
| |
| Keith Thompson 2006-05-09, 7:16 pm |
| Ralf Fassel <ralfixx@gmx.de> writes:
> * bofh1234@hotmail.com
> | So do I have to free my ptr, or will doing a free(whole struct) be
> | very nice and free all memory including the ptr?
>
> You need one free() for every malloc(), and the free()s need to be in
> reverse order compared to the malloc()s (you first malloc() the
> struct, then the pointer in the struct, but you first free() the
> pointer in the struct, then the struct itself).
>
> So yes, you need to free() the ptr before free()ing the struct.
> Just free()ing the struct will not free() the ptr.
Right -- except that free()s don't *always* have to be done in the
reverse order of the corresponding malloc()s.
When you free() a structure (i.e., call free(ptr), where ptr is a
pointer to the structure), you lose the ability to refer to anything
in that structure. If a member of the structure is your only copy of
a pointer that points to allocated memory, you've created a leak; if
you then try to free the pointer *after* freeing the structure that
contained it, you've invoked undefined behavior. So in that limited
sense, the free()s have to be in the reverse order of the malloc()s.
But that applies only when there's a dependency. For example:
ptr1 = malloc(100);
ptr2 = malloc(200);
...
free(ptr1);
free(ptr2);
If ptr1 and ptr2, and the allocated blocks of memory to which they
point, are completely independent of each other, you can free them in
any order you like.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
| |
| Maurizio Loreti 2006-05-10, 1:19 am |
| Ralf Fassel <ralfixx@gmx.de> writes:
> Use a debugger and find out. Things to check are that temp->ptr
> - is non-NULL when you try to free() it
bzzzzzzzzt, wrongo. free(NULL) is permitted and causes no action; see
ISO-IEC 9899/1999 7.20.3.2 .
--
Maurizio Loreti http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy ROT13: ybergv@cq.vasa.vg
| |
| Ralf Fassel 2006-05-10, 7:19 am |
| * Maurizio Loreti <mlo@foobar.it>
| bzzzzzzzzt, wrongo. free(NULL) is permitted and causes no action;
| see ISO-IEC 9899/1999 7.20.3.2 .
ACK. Seems like my last man-free(3)-cache-update was pre-1999 ;-)
<unsure>
But free(0) once was disallowed in the stone age, wasn't it?
At least our code contains tons of
if (ptr) {free(ptr); ptr = NULL;}
</unsure>
R'
| |
| Ralf Fassel 2006-05-10, 7:19 am |
| * Keith Thompson <kst-u@mib.org>
| Ralf Fassel <ralfixx@gmx.de> writes:
| > You need one free() for every malloc(), and the free()s need to be
| > in reverse order compared to the malloc()s
--<snip-snip>--
| Right -- except that free()s don't *always* have to be done in the
| reverse order of the corresponding malloc()s.
--<snip-snip>--
| But that applies only when there's a dependency.
I know why I hat^H^H^Hdon't love to write documentation... ;-)
R'
| |
| Rafael Almeida 2006-05-10, 1:17 pm |
| On Tue, 09 May 2006 20:51:25 GMT
Keith Thompson <kst-u@mib.org> wrote:
> When you free() a structure (i.e., call free(ptr), where ptr is a
> pointer to the structure), you lose the ability to refer to anything
> in that structure. If a member of the structure is your only copy of
> a pointer that points to allocated memory, you've created a leak; if
> you then try to free the pointer *after* freeing the structure that
> contained it, you've invoked undefined behavior. So in that limited
> sense, the free()s have to be in the reverse order of the malloc()s.
>
I think the following example ilustrates better what you just said. It
makes clear that the pointer that's a structure member is just a
pointer like any other. If you don't have access to a structure member
it doesn't necessarily means that you lost the access for a certain
allocated memory.
#include <stdlib.h>
int main(void)
{
struct person {
char *name;
int age;
} *p;
char *tmp;
p = malloc(sizeof (struct person));
p->name = malloc(15);
tmp = p->name;
/* Change the p->name here anyway you like. */
free(p);
/* The person's name is still accessable now, it's
being freed on the next line. */
free(tmp);
return 0;
}
| |
| Keith Thompson 2006-05-10, 7:15 pm |
| Ralf Fassel <ralfixx@gmx.de> writes:
> * Maurizio Loreti <mlo@foobar.it>
> | bzzzzzzzzt, wrongo. free(NULL) is permitted and causes no action;
> | see ISO-IEC 9899/1999 7.20.3.2 .
>
> ACK. Seems like my last man-free(3)-cache-update was pre-1999 ;-)
>
> <unsure>
> But free(0) once was disallowed in the stone age, wasn't it?
> At least our code contains tons of
> if (ptr) {free(ptr); ptr = NULL;}
> </unsure>
free(NULL) has been legal (doing nothing) at least since the 1989 ANSI
C standard.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
| |
| Barry Margolin 2006-05-11, 1:20 am |
| In article <lnslnhk4rg.fsf@nuthaus.mib.org>,
Keith Thompson <kst-u@mib.org> wrote:
> Ralf Fassel <ralfixx@gmx.de> writes:
>
> free(NULL) has been legal (doing nothing) at least since the 1989 ANSI
> C standard.
"stone age" probably refers to K&R C. Was it allowed then?
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
| Wayne C. Morris 2006-05-11, 1:20 am |
| In article <1147181646.171883.65530@i40g2000cwc.googlegroups.com>,
bofh1234@hotmail.com wrote:
> I agree with both posts. For every malloc there must be a free. The
> problem I have is that when I try to free (temp->ptr) I get a
> backtrace. What am I doing wrong?
It crashes because temp is an invalid pointer. The memory it pointed to
was already freed sometime earlier.
I assume you call your delete function like this:
delvarible(fd, Table1ptr);
Your problem lies in these lines:
sptr = hold->next;
free(hold);
When you change sptr, it only affects sptr. It doesn't change Table1ptr.
The next time the function is called, it's passed the same pointer, which
is no longer valid.
There are several ways to fix it. One way would be to define the parameter
as (struct Table1 **sptr), and modify all references to sptr and delvarible
accordingly.
|
|
|
|
|