free() dumps core with a segfault.

C

Code Raptor

Folks,

I am hitting a segfault while free()ing allocated memory - to make it
short, I have a linked list, which I try to free node-by-node. While
free()ing the 28th node (of total 40), I hit a segfault. This is legacy
code. I tried debugging this problem, and am not able to come up with a
valid reason for this. Following function is being used to free:

void DBFreePUF (DBPUFRec *userp)
{

DBPUFRec *next_userp;

/* Debug start. Added by me to walk over the list to count the nodes.
*/
DBPUFRec *tp = NULL;
DBPUFRec *ap = NULL;
int cntr = 0;
int cntr1 = 0;

tp = userp;
while (tp != NULL) {
ap = tp->next;
tp = ap;
++cntr;
}
sprintf(string, "DBFreePUF: %d nodes.", cntr);
Log(string, INFO|LOG);
/* Debug end */

while (userp != NULL)
{
sprintf(string, "DBFreePUF: in while loop, cnt %d.",
cntr1);
Log(string, INFO|LOG);
next_userp = userp->next;
free(userp);
userp = next_userp;
++cntr1;
}
sprintf(string, "DBFreePUF: %d nodes free()d.", cntr1);
Log(string, INFO|LOG);

return;
}

typedef struct _DBPURec
{
int id;
char description[DB_DESC_LEN]; /* DB_DESC_LEN is 61 */
int person_id;
int slot_number;
int facility;
Date modified;
struct _DBPURec *next;
} DBPUFRec;

Data is properly being assigned to the members - even a strncpy() is
being used while copying stuff into description.

Surprisingly, this code works (or appears to work) fine the first time
I go through it. The free() happens correctly that time. Now the second
time when this function is invoked, it goes off at the 28th node -
which cannot be free()'d.

I printed out individual addresses' of the nodes. First time when
things are success - it prints out these addresses: (snapshot)
DBFreePUF: 40 nodes.
....
DBGetPUF: Allocated node [20] at [81e8c90]
DBGetPUF: Allocated node [21] at [81e8cf0]
DBGetPUF: Allocated node [22] at [81e8d50]
DBGetPUF: Allocated node [23] at [81e8db0]
DBGetPUF: Allocated node [24] at [81e8e10]
DBGetPUF: Allocated node [25] at [81e8e70]
DBGetPUF: Allocated node [26] at [81e8ed0]
DBGetPUF: Allocated node [27] at [81e8f30] ***
DBGetPUF: Allocated node [28] at [81e77f0] ***
DBGetPUF: Allocated node [29] at [81e7850] ***
DBGetPUF: Allocated node [30] at [81e78b0] ***
DBGetPUF: Allocated node [31] at [81e7910]
DBGetPUF: Allocated node [32] at [81e7970]
DBGetPUF: Allocated node [33] at [81e79d0]
DBGetPUF: Allocated node [34] at [81e7a30]
DBGetPUF: Allocated node [35] at [81e7a90]
DBGetPUF: Allocated node [36] at [81e7af0]
....

But when it fails the second time, it my log has:
DBFreePUF: 40 nodes.
....
DBGetPUF: Allocated node [20] at [81e8c90]
DBGetPUF: Allocated node [21] at [81e8cf0]
DBGetPUF: Allocated node [22] at [81e8d50]
DBGetPUF: Allocated node [23] at [81e8db0]
DBGetPUF: Allocated node [24] at [81e8e10]
DBGetPUF: Allocated node [25] at [81e8e70]
DBGetPUF: Allocated node [26] at [81e8ed0]
DBGetPUF: Allocated node [27] at [81e8f30] ***
DBGetPUF: Allocated node [28] at [81e74e8] *** Address changed from
here ***
DBGetPUF: Allocated node [29] at [81e7548] ***
DBGetPUF: Allocated node [30] at [81e75a8] ***
DBGetPUF: Allocated node [31] at [81e7608]
DBGetPUF: Allocated node [32] at [81e7668]
DBGetPUF: Allocated node [33] at [81e76c8]
DBGetPUF: Allocated node [34] at [81e7728]
DBGetPUF: Allocated node [35] at [81e7788]
DBGetPUF: Allocated node [36] at [81e77e8]
....

Here is what gdb tells me:
(gdb) bt
#0 0xb73a8f98 in mallopt () from /lib/tls/libc.so.6
#1 0xb73a7f78 in free () from /lib/tls/libc.so.6
#2 0x080e851a in DBFreePUF (userp=0x81e6d50)
....

malloc() in DBGetPUF() is fine, as its return value is being checked.
The prototype is correctly included for malloc() and strncpy(). The
list is being formed correctly - I have verified that.

I am not sure why this happens, and if that sudden change in the
malloc()'d address is the culprit, mis-aligned memory - but AFAIK,
malloc() returns address of memory that is aligned. What surprises me
is that, it goes through fine for the first time, but does not in the
second.

Thanks in advance. Hope I have not missed out anything while posting
this, which goes against getting me help on this list.

Cheers,
Amar
 
J

Jens.Toerring

Code Raptor said:
I am hitting a segfault while free()ing allocated memory - to make it
short, I have a linked list, which I try to free node-by-node. While
free()ing the 28th node (of total 40), I hit a segfault. This is legacy
code. I tried debugging this problem, and am not able to come up with a
valid reason for this. Following function is being used to free:
void DBFreePUF (DBPUFRec *userp)
{
DBPUFRec *next_userp;
int cntr1 = 0;

while (userp != NULL)
{
sprintf(string, "DBFreePUF: in while loop, cnt %d.",
cntr1);
Log(string, INFO|LOG);
next_userp = userp->next;
free(userp);
userp = next_userp;
++cntr1;
}
sprintf(string, "DBFreePUF: %d nodes free()d.", cntr1);
Log(string, INFO|LOG);
}

That doesn't look unreasonable. But since your already printing out
the addresses of the nodes on malloc()ing them it probably will be
interesting to see the addresses before you call free() on them. I
would guess that there will be a surprise for you, i.e. that the
addresses won't be identical to the ones you got from malloc(),
meaning that somewhere in your program you have inadvertently over-
written one of the next pointers. Where that happens is impossible
to say without seeing the complete code. If the addresses aren't
garbled than the mistake is probably even harder to find because
you then must have written over some of the internal data structures
used by the functions for memory allocation. Don't waste your time
looking for more involved explanations;-)

Regards, Jens
 
F

Flash Gordon

I am hitting a segfault while free()ing allocated memory - to make it
short, I have a linked list, which I try to free node-by-node. While
free()ing the 28th node (of total 40), I hit a segfault. This is
legacy code. I tried debugging this problem, and am not able to come
up with a valid reason for this. Following function is being used to
free:

<snip>

I did not see anything obviously wrong with the part of the code you
posted so I would suggest that a memory corruption is occurring
somewhere else. If you are running under Linux I would suggest you try
using valgrind, otherwise try to find a malloc debugger for your
implementation.

You should also try deleting the bits of code you think are not relevant
one at a time until you find which bit is actually responsible or you
have a complete compilable program small enough to post here that
exhibits the problem.

9 times out of 10 a problem like this is actually caused by a piece of
code you believe could not possibly be wrong, so cutting the program
down will often show where the real problem actually is.
 
T

Thomas L.

Code Raptor said:
Folks,

I am hitting a segfault while free()ing allocated memory -
[snip]

I cannot add anything strictly related to the C language and it will
be off-topic for c.l.c for sure, but :
-> if you are in a Linux environment, gives a try at valgrind.
-> if you can compile with GCC (Gnu C Compiler) in a Unix-like
environment, try to set the MALLOC_CHECK_ environment variable to 2
(Bash: export MALLOC_CHECK_=2). It will tell your environment to kill
your program (with an appropriate message) as soon as it messes things
up in malloc's internals (that is what I understood of it) (e.g.
free'ing twice a memory spot). This usually occurs at a place prior to
your deadly free() call. Correcting the first problem can avoid the
subsequent segfault on free().

Know it is off-topic, but hope that helps.
Thomas
 
R

RoSsIaCrIiLoIA

Folks,

I am hitting a segfault while free()ing allocated memory - to make it
short, I have a linked list, which I try to free node-by-node. While
free()ing the 28th node (of total 40), I hit a segfault. This is legacy
code. I tried debugging this problem, and am not able to come up with a
valid reason for this. Following function is being used to free:

I have a similar problem that can have its origin in many functions
wrote in C, C++ assembly. This is the right excuse for write a
malloc-free routine based on the one in K&R book (and some other
routine that check for memory leak and find where memory is re-written
out of bounds).
 
M

Matthew Fisher

Code Raptor said:
Folks,

I am hitting a segfault while free()ing allocated memory - to make it
short, I have a linked list, which I try to free node-by-node. While
free()ing the 28th node (of total 40), I hit a segfault. This is legacy
code. I tried debugging this problem, and am not able to come up with a
valid reason for this. Following function is being used to free:
....
Cheers,
Amar

Amar,

As others have stated you really need a malloc debugger to figure out
this sort of error. There are several good free ones available. You
can try Valgrind if you are on Linux. mpatrol is a good one that is
widely ported. My company markets Dynamic Leak Check for this purpose.
It runs on Solaris and Linux. Windows has BoundsChecker. Purify is
widely ported.

Your subsequent explanation did not fully explain the core dump,IMO.
Some common problems are double freeing a pointer, freeing a point to
non-heap memory, freeing a pointer and then reallocing it and
overrunning an allocated block. Any good memory debugger will find
these sorts of problems.

Matthew
Dynamic Memory Solutions
www.dynamic-memory.com
 
R

RoSsIaCrIiLoIA

Folks,

I am hitting a segfault while free()ing allocated memory - to make it
[...]
I have a similar problem that can have its origin in many functions
wrote in C, C++ assembly. This is the right excuse for write a
malloc-free routine based on the one in K&R book (and some other
routine that check for memory leak and find where memory is re-written
out of bounds).

find, and it is free() that detect errors

typedef double Align;
union header {
struct { union header* ptr;
unsigned size;
}s;
Align x;
};

typedef union header Header;
static Header base;
static Header *freep=NULL;


Header *u, *v;
<code>
Why is it possible?
(u + u->s.size) != v AND (unsigned)(v-u) - u->s.size == 0
 
R

RoSsIaCrIiLoIA

Folks,

I am hitting a segfault while free()ing allocated memory - to make it
[...]
I have a similar problem that can have its origin in many functions
wrote in C, C++ assembly. This is the right excuse for write a
malloc-free routine based on the one in K&R book (and some other
routine that check for memory leak and find where memory is re-written
out of bounds).

find, and it is free() that detect errors

typedef double Align;
^^^^^^

Here I should write long in a x86 CPU?
union header {
struct { union header* ptr;
unsigned size;
}s;
Align x;
};

typedef union header Header;
static Header base;
static Header *freep=NULL;


Header *u, *v;
<code>
Why is it possible?
(u + u->s.size) != v AND (unsigned)(v-u) - u->s.size == 0

(for references see K&R2 chapter 8.7 )
the case is this function that print like |v=67868 u=8080|0|v=x u=etc
(*if* free_mem() free all memory and more than
1024*sizeof(Header)=Nalloc*sizeof(Header) bytes allocated )

void leggi_mem(void)
{Header *u, *v;
unsigned j;
/*----------------*/
for(u=freep; u!=0 ; )
{
printf("|v=%u s=%u|",
(unsigned)(u+1)/(unsigned)sizeof(Header), u->s.size);
if(u->s.ptr==freep) break; /* fatto il giro completo */
v = u->s.ptr;
if((u + u->s.size) != v)
{
j = (unsigned)(v-u) - u->s.size;
if(j<123456) printf("%u", j);
/* ^^^^^ this seems write 0 too */
else printf("#");
}
u = v;
}
}
I think that that "0" means one unsigned int.
 

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,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top