Debuggers For FronTier
FronTier has its own debugger, maintained by its developers.
This debugger is essentially a smart version of printing, which
can be turned on or off through a keyword from the input file.
The developer can change the flow of the code when the keyword is chosen,
and produce for instance additional output, or
initiate additional diagnostics.
We have such a system for a number of important reasons:
- Sophisticated debuggers are usually not available on new architectures.
- FronTier is a heavy user of pointers, a place where many
standard debuggers have deficiences.
- The structures used by FronTier are complicated.
It is important to be able make intelligently structured output for debugging.
For instance you may suspect that something is wrong in a structure
or in some element in a huge array. To be able to redirect the code
to produce easily comprehended output is a big asset.
- This debugging system is part of the development of new code, where most bugs arise.
Since it is maintained it indicates places where bugs existed at some point, and
can provide already comprehensible information. This feature is particularly
important when one needs to debug an unfamiliar part of the code.
- This debugging system remains in the code: just remove the
keyword from the the input file when you are done! No need to recompile.
- When trying to locate a bug, it is not necessary to recompile
part of the code with the "-g" option, for use with UNIX debuggers.
A systematic use of this debugging system can tremendously shorten the
time required to find the troubled area.
The debugging system is explained in "util/debug.c". The list of debugging keywords
is initiated by the user in the very beginning of input to FronTier:
: debug
: file
: keyword_1
: keyword_2
(etc)
: keyword_n
: end
and the code memorizes the sequence of keywords "keyword_1",....,"keyword_n".
Whenever FronTier sees the command:
debug("keyword",string);
It will print "string", if "keyword" is in the list.
The function "debugging("keyword")" returns TRUE exactly when the "keyword" is in the
list. A typical debugging fragment is then:
if(debugging("keyword"))
{
STUFF
}
A good first choice for keyword is as the name of the function
in which debugging needs to be done. It is defined in "util/fnamedebug.h", and works
as follows:
return_type my_function(argument_list)
{
set_function_name(my_function) /* defines a string "my_function" */
DEBUG_ENTER /* prints: "Entered my_function", when
my_function is a keyword */
STUFF
if(DEBUG) /* DEBUG is TRUE, if my_function is keyword */
{
STUFF for debugging
}
DEBUG_LEAVE /* prints: "Left my_function", when
my_function is a keyword */
return (whatever);
}
We insist that new functions added to the code have this structure
A last use of this debugging system is for tracing back at "clean_up".
FronTier maintains two lists:
-
A list of the last 50 calls to the function "debug".
- A list of the last 50 encounters of a new (i.e. different from the last) keyword.
Within a loop one can encounter the same debug string, thousands of times.
This list is therefore often more useful in understanding the flow of the code,
up to the point of error.
Unless the code ends with a succesfull run ("ERROR = 0"), the function "clean_up"
will print these two lists. This allows some form of localization of the error.
Most UNIX systems have various C-program debuggers.
Besides serving debugging purposes, they can give a very quickly a good idea
of the logic of a code segment.
To run FronTier from UNIX debuggers requires a
specially formatted input
- Sparc
- dbx, dbxtool (dbx with graphical interface)
- Sgi
- dbx, xdbx (dbx with graphical interface), and CVD (most useful).
- Galaxy
- ddd, a visual frontend to dbx, xdbx or gdb.
These debuggers require symbol tables for the files you want to look at.
As a result parts of FronTier relevant to your investigation have to be compiled with
the "-g" option. The best thing to do is:
- Touch the files you want to debug on: touch file.c
Remember that touching a header file (file.h) can mean that a substantial part
of FronTier will recompile.
- Go to your libs/PHYSICS directory and type:
mk DBX=-g physics &
where physics is the name of your physics.
FronTier recompiles, see Making FronTier .
- Advantages
- Standard Debuggers will give you a very good idea of the flow of FronTier,
they will allow you to find some run-time errors (for instance segmentation violations)
very easily, and allow to check how every variable changes.
- Disadvantages
- Most generic debuggers have difficulties with pointers
- Pointers to Functions: the debugger may give you only the address, rather than the name.
- Long Arrays: most debuggers do not provide a good way of printing a
pointer which points to a long array of objects.
When you know that one element in the array is wrong you have to figure out which one
it is, and then try to figure out which routine caused this entry to be wrong.
Stopping the code from the debugger at the right place to see how the error arises
can be a nightmare.
Debuggers can provide you with an ernormous of detailed information.
It is easy to forget that the place where you find the error first (bug symptom),
and the place where the error is created (the bug) may be totally unrelated.
User-friendly debuggers are not the first priority of developers of new platforms.
As a result generic debuggers for new platforms are usually primitive, and themselves
buggy.
Back to Main Page
Comments?
Authors:
Folkert Tangerman
Last revision:
December 2, 1998
Copyright 1997 This article may be
redistributed to other individuals for noncommercial use, provided that the
entire text, all HTML codes, and this copyright notice remains intact and
unaltered in any way. This article may not be resold, reprinted, or
redistributed in whole or in part for compensation of any kind without prior
written permission of the author.