[comp.sys.mac.programmer] 'am I dead yet?', or, debugging

ramaley@csli.Stanford.EDU (Alan Ramaley) (10/25/90)

Okey dokey.  I'm using a Mac SE with Think C 4.0.

I spent my entire summer working on a text editor for the blind.  It's
purty cool, with interruptable speech (thanx Berkeley), goofy
selection tools, etc., etc.  It's a huge program, uses dozens of
objects, sprawls, eats up memory, includes about 50 files, etc.

The problem?  Everytime I run it, it crashes at some point.  And it
crashes completely, that is, the think C debugger breaks, I don't even
get a 'bus error' or anything like that.

The program has grown beyond the point of comprehension.  I would step
through with the debugger, but the problem could be anywhere, and it
usually takes five minutes or so to show up.

Is there any way to...

(1)	Have Think C generate quietly a list of code it executes, so
that when the program explodes, I can look in this file, and try to
figure out the last line it executed before the crash, or at least
figure out what code file the crash was in?

(2)	Figure out where you are in the program using the debugger?

I'm sure this kind of program-sprawl-can't-find-the-offending-code
problem has struck others.  Could you share your solutions?
							--Alan

rfischer@Neon.Stanford.EDU (Raymond C. Fischer) (10/25/90)

In article <15998@csli.Stanford.EDU> ramaley@csli.Stanford.EDU (Alan Ramaley) writes:
>The problem?  Everytime I run it, it crashes at some point.  And it
>crashes completely, that is, the think C debugger breaks, I don't even
>get a 'bus error' or anything like that.
>
>(2)	Figure out where you are in the program using the debugger?

Think C's debugger, while very good, probably won't do it for you.
What I do is turn off the C debugger, let the program die, then use 
Macsbug to find out what's doing.  In particular, use the commands ...
  HC (heap check) to see if your trashing the heap
  SC6 (stack crawl) to trace through the activation records, and
  SC7 (stack crawl) in case SC6 doesn't work.
You should have compiled your program with the 'Macsbug Symbols' option
checked so you can actual procedure names displayed.

Taking a wild guess at your problem, I'd say that you're assuming some
handle is in a place it no longer occupies.  Keep in mind that the object
of a handle can move.  If you use a pointer to an object over many system
calls, the object may move and you will overwrite the wrong thing.

Ray Fischer
rfischer@cs.stanford.edu

tel@adimail.UUCP (Terry Monks) (10/25/90)

> 
> I'm sure this kind of program-sprawl-can't-find-the-offending-code
> problem has struck others.  Could you share your solutions?
> 							--Alan

The article called "CTrace - a message logging class" in this month's
(November, actually) Dr. Dobb's JOurnal may be just what you are
looking for if you are using the Think Class Library. If not, you may
have created a monster. It sure sounds like it.


-- 
Terry Monks        Automata Design Inc    (703) 472-9400

russotto@eng.umd.edu (Matthew T. Russotto) (10/26/90)

In article <15998@csli.Stanford.EDU> ramaley@csli.Stanford.EDU (Alan Ramaley) writes:

>The problem?  Everytime I run it, it crashes at some point.  And it
>crashes completely, that is, the think C debugger breaks, I don't even
>get a 'bus error' or anything like that.
>
>The program has grown beyond the point of comprehension.  I would step
>through with the debugger, but the problem could be anywhere, and it
>usually takes five minutes or so to show up.
>
>Is there any way to...

>(2)	Figure out where you are in the program using the debugger?
>
>I'm sure this kind of program-sprawl-can't-find-the-offending-code
>problem has struck others.  Could you share your solutions?


Things get much better if you can localize the crash to a set of procedures--
I think that using the profile code, you can get a list of procedures 
executed to be output.  


--
Matthew T. Russotto	russotto@eng.umd.edu	russotto@wam.umd.edu
      .sig under construction, like the rest of this campus.

alain@atr-hr.atr.co.jp (Alain de Cheveigne) (10/26/90)

In article <1990Oct25.174509.10250@eng.umd.edu> russotto@eng.umd.edu (Matthew T. Russotto) writes:

>In article <15998@csli.Stanford.EDU> ramaley@csli.Stanford.EDU (Alan Ramaley) writes:
...
>>The program has grown beyond the point of comprehension.  I would step
>>through with the debugger, but the problem could be anywhere, and it
>>usually takes five minutes or so to show up.
...
>>I'm sure this kind of program-sprawl-can't-find-the-offending-code
>>problem has struck others.  Could you share your solutions?
>
>
>Things get much better if you can localize the crash to a set of procedures--
>I think that using the profile code, you can get a list of procedures 
>executed to be output.  

In my experience its not that useful to know what the program was doing
just before the crash.  A typical bug causes some random bit of memory
to be crushed (for example writing beyond the end of an array, or to
where a handle block was supposed to be but isn't).  The program trips 
on it and crashes, often much later.  Knowing exactly when and how this
happens often gives little indication as to where the real bug is.

The only solution I know (beyond choosing another way in life...) is to
double-check the code, especially for things like unlocked handles.  
I've found the following macro to be useful:

#define CHECK_EM  1  /* if true, validity tests are performed */

#if CHECK_EM
#define CHECKLOCK(h) checkLock((Handle) h,#h,__FILE__,__LINE__)
#else
#define CHECKLOCK(h) 		
#endif

You just insert a CHECKLOCK() everytime you need to be *sure* a handle is 
locked (particularly where you *are* sure it is...).  There is ultimately no 
performance penalty because you can undefine CHECK_EM once the
program is fully debugged.

The checkLock() function checks the state of the handle, in addition
to doing a whole set of sanity checks:
* is the handle address non-nil, and even?
* does it point within either system or application heap?
* does it point within the zone it says it belongs to (using HandleZone())?
* is the master pointer non-nil and even?
* does it point within the same zone as the handle ?
* does RecoverHandle() return the handle itself ?

I'll post this and other functions and macros if there is interest, 
and if some guru (maybe at Apple?) agrees to look them over first
(are SysZone and ApplZone ok to use?  How about MemTop?).


Alain de Cheveigne
alain@atr-hr.atr.co.jp

ts@cup.portal.com (Tim W Smith) (10/27/90)

You can have TMON record the last N traps your program does.
This can give you some idea of where you are crashing.

					Tim Smith

oster@well.sf.ca.us (David Phillip Oster) (10/28/90)

Macsbug v6 and newer also has:
ATR -- begin trap recording
ATP -- type out on screen info about the last 2 dozen traps.

Most random death after 'n' minutes crashes are caused by unlocked handles.
test under heap scramble (HS) in Macsbug. Consider using the Check heap
before each trap command in MacsBug, and use the Mr. Bus Error INIT, available
on the developer's CDs, which will help you catch NIL pointer dereference
errors.  (It is amazing how much commerical software out there shows up
as buggy under Mr. Bus Error.)
-- 
-- David Phillip Oster - Note new signature. Old one has gone Bye Bye.
-- oster@well.sf.ca.us = {backbone}!well!oster

jlee4@lion.uwaterloo.ca (Johnny Lee) (10/29/90)

In article <21389@well.sf.ca.us> oster@well.sf.ca.us (David Phillip Oster) writes:
>Macsbug v6 and newer also has:
>ATR -- begin trap recording
>ATP -- type out on screen info about the last 2 dozen traps.
>
>Most random death after 'n' minutes crashes are caused by unlocked handles.
>test under heap scramble (HS) in Macsbug. Consider using the Check heap

From co-workers' experience, heap scrambling in Macsbug seems to be
less stable than heap scrambling under TMON.

>-- David Phillip Oster - Note new signature. Old one has gone Bye Bye.
>-- oster@well.sf.ca.us = {backbone}!well!oster

Now where is that TMON Professional version?

Johnny Lee
jlee4@lion.waterloo.edu

mneerach@iiic.ethz.ch (Matthias Ulrich Neeracher) (11/01/90)

In article <1990Oct28.203959.13176@watdragon.waterloo.edu> jlee4@lion.uwaterloo.ca (Johnny Lee) writes:
>From co-workers' experience, heap scrambling in Macsbug seems to be
>less stable than heap scrambling under TMON.

What do you mean with this ? If you just mean that it causes more crashes with
incorrect programs, Macsbug is actually better than TMON. Or does Macsbug
heap scramble cause crashes in correct programs ?

Matthias

-----
Matthias Neeracher                                   mneerach@iiic.ethz.ch
   "These days, though, you have to be pretty technical before you can 
    even aspire to crudeness." -- William Gibson, _Johnny Mnemonic_