Posts Tagged 'debugging'

Displaying numbers with qDebug

Following up on my last post about using qDebug to write logging information to a file, I’ve noticed that there is some confusion about how to best use qDebug.  qDebug is limited – it expects a QByteArray (or similar) because it is converting that directly into a char * string for output (about as simple as you can get).  However, most people want to write more information than just a simple byte array to the output stream.  Below are some examples:

//Basic qDebug call
qDebug("My debug text");
//Basic Output using QString
QString text = "My debug text";
qDebug(text.toAscii());
//Debug string with number
int times = 5;
qDebug("Loop was run "+QString::number(times).toAscii()+" times");

To output a number, the easiest way is to use QString’s static method ‘number’ to create a new QString and then output the QByteArray to qDebug.

Writing Qt Debug Information to a File

Update: I’ve added some additional information on limiting logging when compiling in release mode.

Common problem: I’ve got a Qt app with debugging information, and have a bug that only appears when the code is compiled using the release makefile.

I’ve had this a happen a few times.  By default, the debugging information is written to the debugger console, but when running a compiled ‘release’ app, there is no debugging console and thus no way to get the output.

Solution: Turn on debugging messages in the release makefile and have Qt write the messages to a log file.

Step 1: Remove the -DQT_NO_DEBUG flag from your release makefile.  This will increase the size of the app, though by how much depends on the amount of debugging code in your app.

Step 2: Create a debug message handler function in your main.cpp file.  Here’s an example:

#include <iostream>
#include <fstream> 

#include ...

using namespace std;

ofstream logfile;

void MyOutputHandler(QtMsgType type, const char *msg) {
    switch (type) {
        case QtDebugMsg:
            logfile << QTime::currentTime().toString().toAscii().data() << " Debug: " << msg << "\n";
            break;
        case QtCriticalMsg:
            logfile << QTime::currentTime().toString().toAscii().data() << " Critical: " << msg << "\n";
            break;
        case QtWarningMsg:
            logfile << QTime::currentTime().toString().toAscii().data() << " Warning: " << msg << "\n";
            break;
        case QtFatalMsg:
            logfile << QTime::currentTime().toString().toAscii().data() <<  " Fatal: " << msg << "\n";
            abort();
    }
}

Step 2: Install the handler in your main function, like so:

int main(int argc, char *argv[])
{
    logfile.open("logfile.txt", ios::app);
    #ifndef QT_NO_DEBUG_OUTPUT
    qInstallMsgHandler(MyOutputHandler);
    #endif
    ...
}

Now all debug information will be written with the time to a log file called ‘logfile.txt’ in your application directory.

When compiling your final application, be sure to add the flags -DQT_NO_DEBUG and -DQT_NO_DEBUG_OUTPUT.  These will reduce the application size and ensure that the logfile isn’t used.  Alternately, you can keep NO_DEBUG_OUTPUT out of the makefile if you still want the logfile.