Go to the first, previous, next, last section, table of contents.

Debugging

GNU Emacs has two debuggers, debug and edebug. The first is built into the internals of Emacs and is always with you; the second is an extension to Emacs that has become part of the standard distribution in version 19.

Both debuggers are described extensively in section `Debugging Lisp Programs' in The GNU Emacs Lisp Reference Manual. In this chapter, I will walk through a short example of each.

debug

Suppose you have written a function definition that is intended to return the sum of the numbers 1 through a given number. (This is the triangle function discussed earlier. See section Example with decrementing counter, for a discussion.)

However, your function definition has a bug. You have mistyped `1=' for `1-'. Here is the broken definition:

(defun triangle-bugged (number)
  "Return sum of numbers 1 through NUMBER inclusive."
  (let ((total 0))
    (while (> number 0)
      (setq total (+ total number))
      (setq number (1= number)))      ; Error here.
    total))

If you are reading this in Info, you can evaluate this definition in the normal fashion. You will see triangle-bugged appear in the echo area.

Now evaluate the triangle-bugged function with an argument of 4:

(triangle-bugged 4)

You will produce an error message that says: 

Symbol's function definition is void: 1=

In practice, for a bug as simple as this, this error message will tell you what you need to know to correct the definition. However, suppose you are not quite certain what is going on?

You can turn on debugging by setting the value of debug-on-error to t:

(setq debug-on-error t)

This causes Emacs to enter the debugger next time it encounters an error.

You can turn off debug-on-error by setting it to nil:

(setq debug-on-error nil)

Set debug-on-error to t and evaluate the following:

(triangle-bugged 4)

This time, Emacs will create a buffer called `*Backtrace*' that looks like this:

---------- Buffer: *Backtrace* ----------
Signalling: (void-function 1=)
  (1= number))
  (setq number (1= number)))
  (while (> number 0) (setq total (+ total number))
        (setq number (1= number))))
  (let ((total 0)) (while (> number 0) (setq total ...)
        (setq number ...)) total))
  triangle-bugged(4)
  eval((triangle-bugged 4))
  eval-last-sexp(nil)
* call-interactively(eval-last-sexp)
---------- Buffer: *Backtrace* ----------

(I have reformatted this example slightly; the debugger does not fold long lines.)

You read the `*Backtrace*' buffer from the bottom up; it tells you what Emacs did that led to the error. In this case, what Emacs did was make an interactive call to C-x C-e (eval-last-sexp), which led to the evaluation of the triangle-bugged expression. Each line above tells you what the Lisp interpreter evaluated next.

The third line from the top of the buffer is

(setq number (1= number))

Emacs tried to evaluate this expression; in order to do so, it tried to evaluate the inner expression shown on the second line from the top:

(1= number)

This is where the error occurred; as the top line says:

Signalling: (void-function 1=)

You can correct the mistake, re-evaluate the function definition, and then run your test again.

If you are reading this in Info, you can now turn off debug-on-error by setting it to nil:

(setq debug-on-error nil)

debug-on-entry

A second way to start debug on a function is to enter the debugger when you call the function. You can do this by calling debug-on-entry.

Type:

M-x debug-on-entry RET triangle-bugged RET

Now, evaluate the following:

(triangle-bugged 5)

Emacs will create a `*Backtrace*' buffer and tell you that it is beginning to evaluate the triangle-bugged function:

---------- Buffer: *Backtrace* ----------
Entering:
* triangle-bugged(5)
  eval((triangle-bugged 5))
  eval-last-sexp(nil)
* call-interactively(eval-last-sexp)
---------- Buffer: *Backtrace* ----------

In the `*Backtrace*' buffer, type d. Emacs will evaluate the first expression in triangle-bugged; the buffer will look like this:

---------- Buffer: *Backtrace* ----------
Beginning evaluation of function call form:
* (let ((total 0)) (while (> number 0) (setq total ...)
        (setq number ...)) total))
  triangle-bugged(5)
* eval((triangle-bugged 5))
  eval-last-sexp(nil)
* call-interactively(eval-last-sexp)
---------- Buffer: *Backtrace* ----------

Now, type d again, eight times, slowly. Each time you type d, Emacs will evaluate another expression in the function definition. Eventually, the buffer will look like this:

---------- Buffer: *Backtrace* ----------
Beginning evaluation of function call form:
* (setq number (1= number)))
* (while (> number 0) (setq total (+ total number)) 
        (setq number (1= number))))
* (let ((total 0)) (while (> number 0) 
        (setq total ...) (setq number ...)) total))
  triangle-bugged(5)
* eval((triangle-bugged 5))
  eval-last-sexp(nil)
* call-interactively(eval-last-sexp)
---------- Buffer: *Backtrace* ----------

Finally, after you type d two more times, Emacs will reach the error, and the top two lines of the `*Backtrace*' buffer will look like this:

---------- Buffer: *Backtrace* ----------
Signalling: (void-function 1=)
* (1= number))
...
---------- Buffer: *Backtrace* ----------

By typing d, you were able to step through the function.

You can quit a `*Backtrace*' buffer by typing q; this quits the trace, but does not cancel debug-on-entry.

To cancel the effect of debug-on-entry, call cancel-debug-on-entry and the name of the function, like this:

M-x cancel-debug-on-entry RET triangle-debugged RET

(If you are reading this in Info, cancel debug-on-entry now.)

debug-on-quit and (debug)

In addition to setting debug-on-error or calling debug-on-entry, there are two other ways to start debug.

You can start debug whenever you type C-g (keyboard-quit) by setting the variable debug-on-quit to t. This is useful for debugging infinite loops.

Or, you can insert a line that says (debug) into your code where you want the debugger to start, like this:

(defun triangle-bugged (number)
  "Return sum of numbers 1 through NUMBER inclusive."
  (let ((total 0))
    (while (> number 0)
      (setq total (+ total number))
      (debug)                         ; Start debugger.
      (setq number (1= number)))      ; Error here.
    total))

The debug function is described in detail in section `The Lisp Debugger' in The GNU Emacs Lisp Reference Manual.

The edebug Source Level Debugger

Edebug normally displays the source of the code you are debugging, with an arrow at the left that shows which line you are currently executing.

You can walk through the execution of a function, line by line, or run quickly until reaching a breakpoint where execution stops.

Edebug is described in section `Edebug' in The GNU Emacs Lisp Reference Manual.

Here is a bugged function definition for triangle-recursively. See section Recursion in Place of a Counter, for a review of it. This example is presented without indentation to the left of the defun, as explained below.

(defun triangle-recursively-bugged (number)
  "Return sum of numbers 1 through NUMBER inclusive.
Uses recursion."
  (if (= number 1)                   
      1                              
    (+ number                        
       (triangle-recursively-bugged   
        (1= number)))))               ; Error here.

Normally, you would install this definition by positioning your cursor after the function's closing parenthesis and typing C-x C-e (eval-last-sexp) or else by positioning your cursor within the definition and typing C-M-x (eval-defun). (By default, the eval-defun command works only in Emacs Lisp mode or in Lisp Interactive mode.)

However, to prepare this function definition for Edebug, you must first instrument the code using a different command. In Emacs version 19, you can do this by positioning your cursor within the definition and typing the following:

M-x edebug-defun RET

This will cause Emacs to load Edebug automatically if it is not already loaded, and properly instrument the function. (After loading Edebug, you can use its standard keybindings, such as C-u C-M-x (eval-defun with a prefix argument) for edebug-defun.)

In Emacs version 18, you need to load Edebug yourself; you can do this by putting the appropriate load command in your `.emacs' file.

If you are reading this in Info, you can instrument the triangle-recursively-bugged function shown above. edebug-defun fails to locate the bounds of a definition whose defun line is indented; so the example is presented without the usual spaces to the left of the defun.

After instrumenting the function, place your cursor after the following expression and type C-x C-e (eval-last-sexp):

(triangle-recursively-bugged 3)

You will be jumped back to the source for triangle-recursively-bugged and the cursor positioned at the beginning of the if line of the function. Also, you will see an arrow at the left hand side of that line that looks like this: `=>'. The arrow marks the line where the function is executing.

=>-!-(if (= number 1)

In the example, the location of point is displayed with a star, `-!-' (in Info, it is displayed as `-!-').

If you now press SPC, point will move to the next expression to be executed; the line will look like this:

=>(if -!-(= number 1)

As you continue to press SPC, point will move from expression to expression. At the same time, whenever an expression returns a value, that value will be displayed in the echo area. For example, after you move point past number, you will see the following:

Result: 3 = C-c

This means the value of number is 3, which is ASCII CTL-C (the third letter of the alphabet).

You can continue moving through the code until you reach the line with the error. Before evaluation, that line looks like this:

=>        -!-(1= number)))))               ; Error here.

When you press SPC once again, you will produce an error message that says:

Symbol's function definition is void: 1=

This is the bug.

Press `q' to quit Edebug.

To remove instrumentation from a function definition, simply re-evaluate it with a command that does not instrument it. For example, you could place your cursor after the definition's closing parenthesis and type C-x C-e.

Edebug does a great deal more than walk with you through a function. You can set it so it races through on its own, stopping only at an error or at specified stopping points; you can cause it to display the changing values of various expressions; you can find out how many times a function is called, and more.

Edebug is described in section `Edebug' in The GNU Emacs Lisp Reference Manual.

Debugging Exercises


Go to the first, previous, next, last section, table of contents.