Debugging Parts of Programs

## 14.5 Debugging Parts of Programs

- Mixing debuggable and non-debuggable code

### 14.5.1 Mixing debuggable and non-debuggable code

The debugger can trace only procedures which have been compiled in debug mode. The compiler debug mode is by default switched on and it can be changed globally by setting the flag debug_compile with the set_flag/2 predicate or using dbgcomp/0 or nodbgcomp/0. The global compiler debug mode can be overruled on a file-by-file basis using one of the compiler pragmas

>     :- pragma(nodebug).
>     :- pragma(debug).

Once a program (or a part of it) has been debugged, it can be compiled in nodbgcomp mode so that all optimisations are done by the compiler. The advantages of non-debugged procedures are

- They run slightly faster than the debugged procedures when the debugger is switched off. When the debugger is switched on, the non-debugged procedures run considerably faster than the debugged ones and so the user can selectively influence the speed of the code which is being traced as well as its space consumption.
- Their code is shorter than that of the debugged procedures.

Although only procedures compiled in the dbgcomp mode can be traced, it is possible to mix the execution of procedures in both modes. Then, calls of nodbgcomp procedures from dbgcomp ones are traced, however further execution within nodbgcomp procedures, i.e. the execution of their subgoals, no matter in which mode, is not traced. In particular, when a nodbgcomp procedure calls a dbgcomp one, the latter is normally not traced. There are two important exceptions from this rule:

- When a debuggable procedure has delayed and its DELAY port has been traced, then its RESUME port is also traced, even when it is woken inside non-debuggable code.
- When non-debuggable code meta-calls a debuggable procedure (i.e. via call/1), then this procedure can be traced. This is a useful feature for the implementation of meta- predicates like setof/3, because it allows to hide the details of the setof-implementation, while allowing to trace the argument goal.

Setting a procedure to skipped (with set_flag/3 or skipped/1 ) is another way to speed up the execution of procedures that do not need to be debugged. The debugger will ignore everything that is called inside the skipped procedure like for a procedure compiled in nodbgcomp mode. However, the debugger will keep track of the execution of a procedure skipped with the command s of the debugger so that it will be possible to 'creep' in it on later backtracking or switch the debugger to creep mode while the skip is running (e.g. by interrupting a looping predicate with C and switching to creep mode).
The two predicates trace/1 and debug/1 can be used to switch on the debugger in the middle of a program. They execute their argument in creep or leap mode respectively. This is particularly useful when debugging large programs that take too much time (or need a lot of memory) to run completely with the debugger.

>     [eclipse 1]: debugging.
>     Debugger is switched off

>     yes.
>     [eclipse 2]: big_goal1, trace(buggy_goal), big_goal2.
>     Start debugging - creep mode
>       (1) 0  CALL   buggy_goal %> c creep
>       (1) 0  EXIT   buggy_goal %> c creep
>     Stop debugging.

>     yes.

It is also possible to enable the debugger in the middle of execution without changing the code. To do so, use set_flag/3 to set the start_tracing flag of the predicate of interest. Tracing will then start (in leap mode) at every call of this predicate1. To see the starting predicate itself, set a spy point in addition to the start_tracing flag:

>     [eclipse 1]: debugging.
>     Debugger is switched off

>     yes.
>     [eclipse 2]: set_flag(buggy_goal/0, start_tracing, on),
>                  set_flag(buggy_goal/0, spy, on).

>     yes.
>     [eclipse 3]: big_goal1, buggy_goal, big_goal2.
>      +(0) 0 CALL  buggy_goal   %> creep
>      +(0) 0 EXIT  buggy_goal   %> creep

>     yes.

In tkeclipse, the debugger can also be started in this way. The tracer tool will popup at the appropriate predicate if it has not been invoked already. The start_tracing flag can also be set with the predicate browser tool.