Actions

Debugging

From Gambit wiki

(This document is a stub.)

Gambit features an internal source debugger, see the User Documentation.

Tracking down mistyped identifiers (i.e. variable and procedure names)

Typically you solve this through compiling your code, i.e. (compile-file X), and then load the compiled object file, i.e. (load "file") or (load "file.o1"). The typical warning message is

*** WARNING -- Variable "namespace-name#identifier-name" used in module "filename.o1" is undefined

In order to track down the line number of the undefined identifier, compile with the with-gvm option. The addressed row numbers are found on the rows starting with "line " above the rows with occurrences of namespace-name#identifier-name in them, in the gvm file.

Tracking down segmentation faults

Typical problem sources

Running (#!void) in code compiled with (declare (not safe)) does produce sigsegv:s. Addressing nonexistant variables in code compiled with (declare (not safe)) may cause this as well, i.e. (string-ref nonexistant-variable 0) or (set! nonexistant-variable 'a-value).

Also, pay attention that all Gambit-internal functions without typechecks are always invoked with correct parameters. These are prefixed with ##. I.e., the car function with typechecks is (car), and the one without typechecks is (##car). Thus, (car #!void) will not be fatal in code compiled with (declare (safe)), though, (##car #!void) may be fatal in code compiled with (declare (safe)). And, as we already concluded, both these expressions are fatal to execute in code compiled with (declare (not safe)).

Compiling Gambit for debugging purposes

Download the latest Gambit sourcecode.

Unpack it, usually you do that through executing tar xvfz gambc-v4_X_X.tgz in your shell.

  • Run the configure script. It is normally compiled with --enable-single-host flipped on. If you want Gambit to dump internal messages to the file "console" in the current directory, also pass the --enable-debug parameter. To see all options, run ./configure --help.
  • Edit the file makefile using your favourite editor. There are at least two rows that contain the sequence -O1 (i.e. dash O one), in the current version that's the two rows starting with FLAGS_OBJ and FLAGS_DYN. Replace -O1 with -g -O0 . The -g option will make your C compiler include debugging symbols on compilation, and the -O0 will force it not to do any optimizations on the assembly/binary code it generates, thus the mapping of rows of C/C++ code into memory addresses during program execution will be the most precise your C/C++ compiler is capable of generating.
  • Compile Gambit through typing make
  • If you want this Gambit to replace your current installation, run make install

Running compile-file with debugging options flipped on

When running (compile-file ), remember to pass the cc-opts: "-g -O0" .

Also, there are the options:

  • track-scheme to make the C/C++ compiler use the source Scheme code instead of the source C/C++ code for debugging info. This is an option that you may want to vary during debugging work.
  • keep-c to make compile-file not remove the intermediary C/C++ code file.

Run Gambit in GDB

GDB is found on http://sourceware.org/gdb/, and is typically included as an optional package with Linux and BSD distributions.

From your shell, run

gdb gsc

GDB will start. If you want to pass gsc argument, type

set args=[the arguments]

for example

set args=-e "(display \"test\n\")" -

To start Gambit witihn GDB, type run.

If your Gambit application crashes, you will get a prompt in GDB indicating so. To get a backtrace of the stack of your program, type bt . The backtrace should also be interesting for anyone who would assist you in finding the reason to the crash.

To quit, type quit.

Other things you may want to do

There are ample of debug utilities, for different operating systems, that may be interesting for you to use.

For instance, strace is an utility that displays all Kernel invocations your application does. Remember to run it with the -Ff options.

valgrind is an utility that traces memory leaks. (Gambit will not leak memory in itself, but a faulty Foreign Function Interface library could do that.)

Tracking down memory leaks

Superflouous symbols

Symbols are not garbage collected. Thus, if you do (string->symbol X) on gigabytes of string data, then gigabytes of heap space will be permanently allocated for this. If you want to use ample of symbols in your application, use uninterned symbols, generated using make-uninterned-symbol .

Memory leaks in FFI:s

While Gambit garbage collects Scheme objects on its own, objects created by FFI:s may not be garbage collected automatically, and, there may be bugs in FFI:s. If you use an FFI, look at how it should be used carefully, and if you suspect there's a memory leak in it, analyze its sourcecode, and use debug utilities such as valgrind.

Garbage collection threshold

Pay attention to the runtime options h (maximum heapsize in kilobytes) and l (livepercent). See the reference manual for more information. Setting livepercent to five means that garbage collection will take place at the time that there are nineteen times more memory allocated for objects that should be garbage collected, than there is memory allocated for objects that should not. The reason the livepercent option is there, is to give a way to control how sparing/generous the garbage collector should be about memory consumption, vs. how heavy/light it should be in CPU load.