13. Debugging GtkAda applications

This chapter presents a number of technics that can be used when debugging GtkAda applications. First, the standard tools to debug Ada applications can be used:

Compile with -g

You should almost always include debugging information when compiling and linking your code. This gives you the possibility to use the debugger. See below the variable GDK_DEBUG for how to disable grabs.

bind with -E

Using this argument on the gnatbind or gnatmake command line will force the compiler to include backtraces when an exception is raised. These backtraces can be converted to symbolic backtraces by using the addr2line tool.

Link with -lgmem

Using this switch gives access to the gnatmem tool, that helps you to detect memory leaks or doubly-deallocated memory. The latter often results in hard-to-fix Storage_Error exceptions. See the GNAT User’s guide for more information.

There are also a number of technics specific to GtkAda or gtk+ applications. For most of them, you might need to recompile these libraries with the appropriate switches to get access to the extended debugging features.

Use the `–sync` switch

Under unix systems, all applications compiled with gtk+ automatically support this switch, which forces events to be processed synchronously, thus making it easier to detect problems as soon as they happen. This switch is not relevant to Windows systems.

break on g_log

In the debugger, it is often useful to put a breakpoint on the glib function g_log. When gtk+ is linked dynamically, you will need to first start your application with begin, then put the breakpoint and continue the application with cont. This helps understand internal errors or warnings reported by gtk+ and glib

compile glib with `–disable-mem-pools`

Glib, the underlying layer that provides system-independent services to gtk+, has an extensive and optimized system for memory allocation. Bigger chunks of Memory are allocated initially, and then subdivided by glib itself. Although this is extremely performant, this also make the debugging of memory-related problems (storage_error) more difficult. Compiling with the above switch forces glib to use the standard malloc() and free() system calls. On GNU/Linux systems, it might be useful to set the variable MALLOC_CHECK_ to 1 to use error-detecting algorithms (see the man page for malloc()).

compile glib and gtk+ with `–enable-debug=yes`

It is recommended that you specify this switch on the configure command line when compiling these two libraries. In addition to compiling the libraries with debugging information for the debugger, additional runtime debug options (controllable via environment variables) become available. Specifying –enable-debug=no is not recommended for production releases (see glib or gtk+ documentation for details).

For these three variables, the possible values are given below. These are lists of colon-separated keywords. You can choose to remove any of these value from the variable

GOBJECT_DEBUG=objects:signals

This sets up the debugging output for glib. The value @samp{objects} is probably the most useful, and displays, on exit of the application, the list of unfreed objects. This helps detect memory leaks. The second value @samp{signals} will display all the signals emitted by the objects. Note that this results in a significant amount of output.

GDK_DEBUG=updates:nograbs:events:dnd:misc:@*xim:colormap:gdkrgb:gc:pixmap:image:input:cursor

This sets up the debugging output for gdk. The most useful value is @samp{nograbs}, which prevents the application from ever grabbing the mouse or keyboards. If you don’t set this, it might happen that the debugger becomes unusable, since you don’t have access to the mouse when the debugger stops on a breakpoint. Another simpler solution is to debug remotely from another machine, in which case the grabs won’t affect the terminal on which the debugger is running.

GTK_DEBUG=misc:plugsocket:text:tree:updates:keybindings

This sets up the debugging output for gtk. Almost all of these values are mostly for internal use by gtk+ developpers, although @samp{keybindings} might prove useful sometimes.

Import the C function ada_gtk_debug_get_ref_count

This function has the following Ada profile:

function Ref_Count (Add : System.Address) return Guint;
pragma Import (C, Ref_Count, "ada_gtk_debug_get_ref_count");

and should be called in a manner similar to:

declare
   Widget : Gtk_Widget;
   Count  : Guint;
begin
   Count := Ref_Count (Get_Object (Widget));
end;

and returns the internal reference counter for the widget. When this counter reaches 0, the memory allocated for the widget is automatically freed.

This is mostly a debugging aid for people writting their own containers, and shouldn’t generally be needed. You shouldn’t rely on the internal reference counter in your actual code, which is why it isn’t exported by default in GtkAda.