|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** Qt Debugging Techniques
|
|
|
|
**
|
|
|
|
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
|
|
|
|
**
|
|
|
|
** This file is part of the Qt GUI Toolkit.
|
|
|
|
**
|
|
|
|
** This file may be used under the terms of the GNU General
|
|
|
|
** Public License versions 2.0 or 3.0 as published by the Free
|
|
|
|
** Software Foundation and appearing in the files LICENSE.GPL2
|
|
|
|
** and LICENSE.GPL3 included in the packaging of this file.
|
|
|
|
** Alternatively you may (at your option) use any later version
|
|
|
|
** of the GNU General Public License if such license has been
|
|
|
|
** publicly approved by Trolltech ASA (or its successors, if any)
|
|
|
|
** and the KDE Free Qt Foundation.
|
|
|
|
**
|
|
|
|
** Please review the following information to ensure GNU General
|
|
|
|
** Public Licensing requirements will be met:
|
|
|
|
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
|
|
|
|
** If you are unsure which license is appropriate for your use, please
|
|
|
|
** review the following information:
|
|
|
|
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
|
|
|
|
** or contact the sales department at sales@trolltech.com.
|
|
|
|
**
|
|
|
|
** This file may be used under the terms of the Q Public License as
|
|
|
|
** defined by Trolltech ASA and appearing in the file LICENSE.QPL
|
|
|
|
** included in the packaging of this file. Licensees holding valid Qt
|
|
|
|
** Commercial licenses may use this file in accordance with the Qt
|
|
|
|
** Commercial License Agreement provided with the Software.
|
|
|
|
**
|
|
|
|
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
|
|
|
|
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
|
|
|
|
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
|
|
|
|
** herein.
|
|
|
|
**
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\page debug.html
|
|
|
|
|
|
|
|
\title Debugging Techniques
|
|
|
|
|
|
|
|
Here we present some useful hints to debugging your Qt-based software.
|
|
|
|
|
|
|
|
\section1 Command Line Options
|
|
|
|
|
|
|
|
When you run a Qt program you can specify several command line options
|
|
|
|
that can help with debugging.
|
|
|
|
|
|
|
|
\table
|
|
|
|
\header \i Option \i Result
|
|
|
|
\row \i -nograb
|
|
|
|
\i The application should never grab \link QWidget::grabMouse()
|
|
|
|
the mouse\endlink or \link QWidget::grabKeyboard() the
|
|
|
|
keyboard \endlink. This option is set by default when the
|
|
|
|
program is running in the \c gdb debugger under Linux.
|
|
|
|
\row \i -dograb
|
|
|
|
\i Ignore any implicit or explicit -nograb. -dograb wins over
|
|
|
|
-nograb even when -nograb is last on the command line.
|
|
|
|
\row \i -sync
|
|
|
|
\i Runs the application in X synchronous mode. Synchronous mode
|
|
|
|
forces the X server to perform each X client request
|
|
|
|
immediately and not use buffer optimization. It makes the
|
|
|
|
program easier to debug and often much slower. The -sync
|
|
|
|
option is only valid for the X11 version of Qt.
|
|
|
|
\endtable
|
|
|
|
|
|
|
|
|
|
|
|
\section1 Warning and Debugging Messages
|
|
|
|
|
|
|
|
Qt includes three global functions for writing out warning and debug
|
|
|
|
text.
|
|
|
|
\list
|
|
|
|
\i \link ::qDebug() qDebug()\endlink for writing debug output for testing etc.
|
|
|
|
\i \link ::qWarning() qWarning()\endlink for writing warning output when program
|
|
|
|
errors occur.
|
|
|
|
\i \link ::qFatal() qFatal()\endlink for writing fatal error messages
|
|
|
|
and exiting.
|
|
|
|
\endlist
|
|
|
|
|
|
|
|
The Qt implementation of these functions prints the text to the \c stderr
|
|
|
|
output under Unix/X11 and to the debugger under Windows. You can
|
|
|
|
take over these functions by installing a message handler;
|
|
|
|
\link ::qInstallMsgHandler() qInstallMsgHandler()\endlink.
|
|
|
|
|
|
|
|
The debugging functions \l QObject::dumpObjectTree() and \l
|
|
|
|
QObject::dumpObjectInfo() are often useful when an application looks
|
|
|
|
or acts strangely. More useful if you use object names than not, but
|
|
|
|
often useful even without names.
|
|
|
|
|
|
|
|
\section1 Debugging Macros
|
|
|
|
|
|
|
|
The header file \c qglobal.h contains many debugging macros and
|
|
|
|
\c{#define}s.
|
|
|
|
|
|
|
|
Two important macros are:
|
|
|
|
\list
|
|
|
|
\i \link ::Q_ASSERT() Q_ASSERT(b)\endlink where b is a boolean
|
|
|
|
expression, writes the warning: "ASSERT: 'b' in file file.cpp (234)"
|
|
|
|
if b is FALSE.
|
|
|
|
\i \link ::Q_CHECK_PTR() Q_CHECK_PTR(p)\endlink where p is a pointer.
|
|
|
|
Writes the warning "In file file.cpp, line 234: Out of memory" if p is
|
|
|
|
0.
|
|
|
|
\endlist
|
|
|
|
|
|
|
|
These macros are useful for detecting program errors, e.g. like this:
|
|
|
|
\code
|
|
|
|
char *alloc( int size )
|
|
|
|
{
|
|
|
|
Q_ASSERT( size > 0 );
|
|
|
|
char *p = new char[size];
|
|
|
|
Q_CHECK_PTR( p );
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
If you define the flag QT_FATAL_ASSERT, Q_ASSERT will call fatal()
|
|
|
|
instead of warning(), so a failed assertion will cause the program to
|
|
|
|
exit after printing the error message.
|
|
|
|
|
|
|
|
Note that the Q_ASSERT macro is a null expression if \c QT_CHECK_STATE (see
|
|
|
|
below) is not defined. Any code in it will simply not be
|
|
|
|
executed. Similarly Q_CHECK_PTR is a null expression if \c QT_CHECK_NULL is
|
|
|
|
not defined. Here is an example of how you should \e not use Q_ASSERT and
|
|
|
|
Q_CHECK_PTR:
|
|
|
|
|
|
|
|
\code
|
|
|
|
char *alloc( int size )
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
Q_CHECK_PTR( p = new char[size] ); // WRONG!
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
The problem is tricky: \e p is set to a sane value only as long as the
|
|
|
|
correct checking flags are defined. If this code is compiled without
|
|
|
|
the QT_CHECK_NULL flag defined, the code in the Q_CHECK_PTR expression is
|
|
|
|
not executed (correctly, since it's only a debugging aid) and \e alloc
|
|
|
|
returns a wild pointer.
|
|
|
|
|
|
|
|
The Qt library contains hundreds of internal checks that will print
|
|
|
|
warning messages when some error is detected.
|
|
|
|
|
|
|
|
The tests for sanity and the resulting warning messages inside Qt are
|
|
|
|
conditional, based on the state of various debugging flags:
|
|
|
|
\table
|
|
|
|
\header \i Flag \i Meaning
|
|
|
|
\row \i QT_CHECK_STATE \i Check for consistent/expected object state
|
|
|
|
\row \i QT_CHECK_RANGE \i Check for variable range errors
|
|
|
|
\row \i QT_CHECK_NULL \i Check for dangerous null pointers
|
|
|
|
\row \i QT_CHECK_MATH \i Check for dangerous math, e.g. division by 0
|
|
|
|
\row \i QT_NO_CHECK \i Turn off all QT_CHECK_... flags
|
|
|
|
\row \i QT_DEBUG \i Enable debugging code
|
|
|
|
\row \i QT_NO_DEBUG \i Turn off QT_DEBUG flag
|
|
|
|
\endtable
|
|
|
|
|
|
|
|
By default, both QT_DEBUG and all the QT_CHECK flags are on. To turn
|
|
|
|
off QT_DEBUG, define QT_NO_DEBUG. To turn off the QT_CHECK flags,
|
|
|
|
define QT_NO_CHECK.
|
|
|
|
|
|
|
|
Example:
|
|
|
|
\code
|
|
|
|
void f( char *p, int i )
|
|
|
|
{
|
|
|
|
#if defined(QT_CHECK_NULL)
|
|
|
|
if ( p == 0 )
|
|
|
|
qWarning( "f: Null pointer not allowed" );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(QT_CHECK_RANGE)
|
|
|
|
if ( i < 0 )
|
|
|
|
qWarning( "f: The index cannot be negative" );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
\section1 Common bugs
|
|
|
|
|
|
|
|
There is one bug that is so common that it deserves mention here: If
|
|
|
|
you include the Q_OBJECT macro in a class declaration and run the
|
|
|
|
\link moc.html moc\endlink, but forget to link the moc-generated
|
|
|
|
object code into your executable, you will get very confusing error
|
|
|
|
messages. Any link error complaining about a lack of \c{vtbl},
|
|
|
|
\c{_vtbl}, \c{__vtbl} or similar is likely to be a result of this
|
|
|
|
problem.
|
|
|
|
|
|
|
|
*/
|