PDA

Click to See Complete Forum and Search --> : Simple C question - calloc()


HarryW
Jun 5th, 2002, 08:07 AM
Hi all.

I am currently trying to debug some C library code I'm writing for serial port access (on Posix). I'm getting some strange segfaults though.

Does anybody know what I might be doing wrong with this line?

szNewBuffer = (char *)calloc(iBufferLen - iLineLen + 1, 1);

I've managed to isolate this line using stractegically placed printf() statements (if anyone has a better debugging technique I'd like to hear it!)

the expressoin (iBufferLen - iLineLen + 1) evaluates to various numbers depending on the circumstances, but as an example, prior to one particular segfault I've encountered it was 25. So it's not negative or anything silly like that. In this case I'm trying to allocate space for a string of 24 characters.

Any ideas?

HarryW
Jun 5th, 2002, 08:52 AM
Ah, I think I know why this is failing (sort of): the heap has been corrupted by a buffer overrun somewhere. MALLOC_CHECK_=1 is very handy :)

Now I just have to find my buffer overrun....

Zaei
Jun 5th, 2002, 10:04 AM
I would go with assert()s instead of printf()s.


#define DEBUG

#ifdef DEBUG
#define assert(x, y) if(!x) {printf("%s", y); exit(-1);}
#else
#define assert(x, y) ;
#endif

Usage:

assert(10==x, "10!=x in function y()!");


Z.

jim mcnamara
Jun 6th, 2002, 07:01 AM
Do you know how to use gdb? (gnu debugger-- wildebeest)
It will run on all POSIX-compliant systems.

Some guys use assert to initiate debugging via atexit.

HarryW
Jun 6th, 2002, 07:31 AM
I've heard of gdb but never used it. We don't do much C coding in my office (virtually none) but quite a few people (like me) have some background in it. I've heard some mutterings about it being difficult to configure and use, but that might not be true.

Does it make life much easier?

Currently I am trying to find a buffer overrun (a different one resulting in a similar error) somewhere and I am pretty sure I know where it's happening but I'm having trouble working out why. If I could see the state of some of my variables (like you can when you use watches in VB) it would probably be much easier. I really want to see what I've got in my buffer variables too, to see if the buffer lengths I have maintained match the actual data.

jim mcnamara
Jun 6th, 2002, 07:41 AM
You can get gdb from www.gnu.org. You need to install it from root.

What platform are you on? - there are other debuggers, HPUX has one, etc. I personally happen to like gdb, since it means I learn one debugger really well, instead of learning five partially.

jim mcnamara
Jun 6th, 2002, 07:44 AM
PS: it's quite common to overwrite areas of the $TEXT or $DATA segments, especially when you reference data via pointer.

CornedBee
Jun 6th, 2002, 08:24 AM
Is posix 16-bit? Then maybe you have a near/far pointer problem.

HarryW
Jun 6th, 2002, 09:04 AM
I'm working on Linux but the target is HPUX.

It seems I already have it installed, which is nice. I've played about with it and looked at the man/info entries a little. I'm not exactly sure what I'm doing though. It doesn't seem very verbose when you run an executable in it.

$DATA and $TEXT doesn't mean much to me.... would you care to enlighten me? :) The problem I am having is, I am pretty sure, down to an overrun that I can only think must be happening on these lines:

memcpy(sNewBuffer, sBuffer, *piBufferLen);
memcpy(sNewBuffer + *piBufferLen, sData, iDataLen);

I'm trying to maintain data on the lengths of the the buffer of data I have collected from the serial port. I'm picking out strings from the data, delimited by "\r\r\n". I can't really use null-terminated strings though because I am not certain there won't be nulls in the data, so I'm trying to keep a record of the lengths of these strings.

CornedBee
Jun 6th, 2002, 12:47 PM
szNewBuffer = (char *)calloc(iBufferLen - iLineLen + 1, 1);
Isn't that a minus sign there? I'm sure you want to allocate space for both buffer and line, right? Could this be the problem?

parksie
Jun 6th, 2002, 01:22 PM
Originally posted by CornedBee
Is posix 16-bit? Then maybe you have a near/far pointer problem. POSIX is a general standard.

For example, these are all (supposedly!) POSIX-compliant:

BSD, Solaris, Linux, Irix, HP-UX, and so on :)

jim mcnamara
Jun 6th, 2002, 04:34 PM
Using gdb
Starting:
cc -g foo.c

gdb a.out [core] core is optional, if you wanna see your dump
. setting breaks
break [line number in your source]
example: break 1215
break [at routine name]
example: break myfunc

you can also set watches.

when you get where you have a problem
ba -- shows the call stack
step -- executes one line
print variable-name displays a variable
quit - exits gdb
list- shows you the source code where you are +- 10 lines

HarryW
Jun 6th, 2002, 07:19 PM
Cheers Jim. I'll persevere a little with gdb. I have gotten a little closer to finding my problem but I am completely stumped as to why a buffer overrun would be happening - I can't even see any heap variables being changed at the point it's all going wrong. It turns out the problem wasn't where I thought it was ;) Oh well.

Cornedbee, no that's definitely what I want.

I'm off work til Tuesday now (hoorah) so I may be back with more problems then :)

HarryW
Jun 11th, 2002, 08:07 AM
Well I got it all working. Thanks for the help :)