Debugging in R with gdb and Insight

Overview
Compiling with debugging information
Setting up gdb
Running gdb
Insight
Interrupting execution
Attaching to a running process

Overview

On Windows, the recommended compilers for R and packages written in R are the MinGW version of the gcc and g77 compilers. The only debugger that I have used which understands the debugging information produced by gcc is gdb; Insight is a TCL/TK graphical front-end for this compiler. These instructions describe how to set up and use the Cygwin version of gdb.


Compiling with debugging information

The R makefiles check for an environment variable named DEBUG, and if present, call gcc with the -gdwarf-2 option so that debugging information is inserted in the generated code. Other possible choices for debug information are -g, -ggdb, -gcoff, -gstabs and -gstabs+. I don't know what differences there are between the various debug formats. You could edit the Makefile and/or the MakeDll file in src/gnuwin32 to try them out, and let me know.

The debug information lets gdb associate source code with the machine code produced by the compiler, and variable names with memory locations. Without it gdb will still function, but you'll only see disassembled machine code and the occasional public symbol.

To compile the code for an R package with debug information, use one of the following methods. If you have the source installed in RHOME/src/library/mypkg:

make pkgclean-mypkg
make DEBUG=T R_KEEP_PKG_SOURCE=yes
If the source is in the local subdirectory mypkg,
set DEBUG=T
set R_KEEP_PKG_SOURCE=yes
Rcmd INSTALL --preclean mypkg

Compiler optimizations (which re-order instructions, put functions inline, etc.) make debugging difficult, and you may want to set the debugging level to 0. You can do this by putting the line

COPTFLAG=-O0
into a file Makevars.win in the src directory of your package.


Setting up gdb

I'll start by assuming that you have a full Cygwin installation, have installed gdb as part of it, and are working in the default Cygwin shell, ash. Some more flexibility is offered below.

gdb reads a configuration file .gdbinit, which I recommend that you put in your working directory. This file contains a sequence of gdb commands that are executed when gdb starts. Mine (which I keep in my src/gnuwin32 directory) is dissected below.

set disass intel

This line says to use the Intel mnemonics in disassembled code. If you have experience with assembly language programming in DOS or Windows you'll probably want this. If you learned assembler on a Unix machine, you might want the default ATT style disassembly instead.

directory ../main
directory ../nmath
directory ../appl
directory ../extra
directory graphapp
directory ../library/stats/src

The gcc debug information doesn't specify the directory where source files are located, so you'll need to give a search list of directories here where gdb should look for source files (other than the working directory). The list above covers most of the R source code, plus the source code for the stats package.

set env TMP c:/TEMP

Running under Cygwin, directory paths are all messed up. This line is necessary in order that R will start under gdb. I don't know why R runs fine from the command line in Cygwin, but fails under gdb. Just another Cygwin mystery.

If you aren't running within a Cygwin shell, you're likely to run into some problems. The following advice is mostly guesswork rather than the result of careful testing:


Running gdb

You run gdb using a command like
gdb Rgui
which starts up the debugger and leaves you at a command prompt. I honestly don't know how anyone could stand to use the debugger like this, and I don't, so I'm not going to describe how to do it.

Insight

Insight is a somewhat clunky graphical front-end to gdb which makes gdb just barely tolerable to use. You start it using

insight Rgui

and one or more windows open up. (You'll get just one the first time; after that, it will store setup information in the gdbtk.ini file in your home directory, and will return to the windows you had open the last time you quit. Sometimes this file gets corrupted and Insight won't run at all; just delete it and start over.)

The main Insight window (the "Source window") lists the source of the current function. Often this window will be blank on startup, because you won't have debug information for the run-time startup code. Use the View menu item to open other windows, and the Help menu item to see a list of what's available. You can use a view command in the gdb console to open a file in the browser, e.g. view myfunction or view myfile.c:100 to see line 100 of the file.


Interrupting execution

In Unix, gdb uses signals to interrupt the program. I have been unable to get these to work in Windows. I know the following ways to interrupt execution:

Attaching to a running process

Sometimes running R under gdb changes things enough that bugs go away. This happens because R under gdb loads at a different memory address, the memory allocator sees a different heap, etc. Since the first step in debugging is making an error reproducible, it's very frustrating when the debugger changes R's behaviour.

One way to have gdb make less impact on the running process is to attach the debugger after starting R.

To do this, do the following.

  1. Start R and run it almost to the point where the error occurs.
  2. Hit Ctrl-Alt-Del to bring up the Windows Task Manager.
  3. Switch to the Processes tab. You need to determine the process identifier (PID) for the running instance of Rgui.exe. By default this will not be shown, but the View | Select Columns... dialog will let you enable it. Notes:
  4. In a separate window, start gdb or insight. In the gdb console, type attach <PID>, where <PID> is the PID shown in the Task Manager. This will interrupt the R process, and allow you to install breakpoints, examine variables, etc. Use one of the usual gdb commands to resume execution.

Last modified: Sat 20 Mar 2010, by Duncan Murdoch