Qt Debugging Techniques

# Debugging Techniques

Here we present some useful methods for debugging your Qt-based software.

## Command Line Options

When you run a Qt program you can specify several command line options that can help with debugging.

- -nograb The application should never grab the mouse or the keyboard. This option is set by default when the program is running in the `gdb` debugger under Linux.
- -dograb Ignore any implicit or explicit -nograb. -dograb wins over -nograb even when -nograb is last on the command line.
- -sync Runs the application in X synchronous mode. Synchronous mode forces the X server perform each X client request immediately and not use a buffer optimizaton. It makes the program easier to debug and often much slower. The -sync option is only valid for the X11 version of Qt.

(Note that these options are only available in the development version of the Qt library, not in the production version. Currently, Troll Tech only supports a development version of the Qt library.)

## Warning and Debugging Messages

Qt includes three global functions for writing out warning and debug text.

- debug() for writing debug output for testing etc.
- warning() for writing warning output when program errors occur.
- fatal() for writing fatal error messages and exit.

The Qt implementation of these functions prints the text to the `stderr` output under Unix/X11 and to the debugger under Windows. You can take over these functions by installing a message handler; qInstallMsgHandler().

## Debugging Macros

The header file qglobal.h contains many debugging macros and #defines.

Two important macros are:

- ASSERT(b) where b is a boolean expression, writes the warning: "ASSERT: 'b' in file file.cpp (234)" if b is FALSE.
- CHECK_PTR(p) where p is a pointer. Writes the warning "In file file.cpp, line 234: Out of memory" if p is null.

These macros are useful for detecting program errors, e.g. like this:

      char *alloc( int size )
      {
          ASSERT( size > 0 );
          char *p = new char[size];
          CHECK_PTR( p );
          return p;
      }

Note that the CHECK_PTR macro is a null expression if `CHECK_NULL` (see below) is not defined. Any code in it will simply not be executed. Here is an example of how you should NOT do it:

      char *alloc( int size )
      {
          char *p;
          CHECK_PTR( p = new char[size] );  // never do this!
          return p;
      }

Very tricky: p is set to a sane value only if you're debugging. When you're ready to ship, that code is not executed (correctly, since it's only a debugging aid) and alloc returns a wild pointer.

The Qt development library contains hundreds of warning messages that are printed when some error is detected.

The warning messages inside Qt are conditional, based on the state of various debugging flags:

- `CHECK_STATE:` Check for consistent/expected object state
- `CHECK_RANGE:` Check for variables range errors
- `CHECK_NULL:` Check for dangerous null pointer
- `NO_CHECK:` Turn off all CHECK_... flags
- `DEBUG:` Enable debugging code
- `NO_DEBUG:` Turn off DEBUG flag

Example:

      void f( char *p, int i )
      {
      #if defined(CHECK_NULL)
          if ( p == 0 )
              warning( "f: Null pointer not allowed" );
      #endif

      #if defined(CHECK_RANGE)
          if ( i < 0 )
              warning( "f: The index cannot be negative" );
      #endif
      }