Debugging with the console and editor

There are other ways that you can debug your app in addition to using the debugger. These methods involve using the console and editor to perform the following tasks:

Use console.log() to output to the console

In QML/JavaScript, you can use the console.log() function to output text and variables to the console.

For example, in the CustomControl tutorial, the app captures the valueChanged() signal and outputs the slider value to the console when the value changes:

CircularSlider {
    layoutProperties: DockLayoutProperties {
        horizontalAlignment: HorizontalAlignment.Center
        verticalAlignment: VerticalAlignment.Center
    }
    onValueChanged: {
        console.log("Slider value: " + value);
    }
}

Use qDebug() to output to the console

In C++, a common way to output text and variables to the console is by using the qDebug() function. Here's an example of how QCompass readings are displayed:

 QCompassReading *reading = m_CompassSensor->reading(); 

qreal azimuth = reading->azimuth();
qDebug() << "The azimuth is" << azimuth << "degrees."; 

Use fprintf() to output to the console

You can use the fprintf() function with stdout or stderr as the output stream to send output directly to the console. Or, you can use a function similar to the following:

void myMessageOutput(QtMsgType type, const char* msg){
    fprintf(stdout, "%s\n", msg);                
    fflush(stdout); 
} 

Then, you can register this handler function with qDebug by calling the qInstallMsgHandler() function in your main function after the default Application is created, similar to the following:

int main(int argc, char **argv)
{
    Application app(argc, argv);
    qInstallMsgHandler(myMessageOutput);

    // ...

}

Now, qDebug() calls are logged to the console.

Console logging and qDebug() output debug messages to the console only when the myMessageOutput() function is declared and registered. You should remove this code when the app is ready for release.

Use Qt debugging macros and functions

The QtGlobal header file contains some useful debugging macros and functions in addition to qDebug():

  • Q_ASSERT() is useful for testing functions that return a Boolean value.
  • qWarning() displays a warning message in the console.
  • qFatal() closes the app and creates a core dump that you can use for debugging.

You can use these macros and functions to test various conditions in your apps. For example, consider signal-slot connections in code samples. To ensure that your app works as you designed, you must evaluate the Boolean value that the QObject::connect() function returns. A signal-slot connection fails if the sender or receiver objects are invalid or the types of the signal arguments are not registered in Qt as meta-types. In these cases, Qt generates a warning that is posted to slog2info log files on the device.

You should use the Q_ASSERT() macro to evaluate the return value of connect(), as suggested in Using predefined signals.

This technique affects only the debug builds of your code because the release builds define QT_NO_DEBUG, which disables Q_ASSERT(). Because all apps and libraries (including Qt) are released in release mode (not debug mode), the handling of the connect() return values using Q_ASSERT() doesn't affect published apps. This technique has no code to recover from a failed connection because it assumes that there is no safe recovery.

// If any Q_ASSERT statement(s) indicate that the slot failed 
// to connect to the signal, make sure you know why this happened. 
// This is not normal, and will cause your app to stop working!
bool connectResult;
  
// Since the variable is not used in the app, this is added to avoid 
// a compiler warning.
Q_UNUSED(connectResult);
  
connectResult = QObject::connect(smokeDetector, 
                                 SIGNAL(smokeDetected()), 
                                 sprinkler,     
                                 SLOT(dispenseWater()));
                                   
// This affects only Debug builds.
Q_ASSERT(connectResult);

You can also check the return value of the connect() function using an if statement and add some code to recover from the failed connect(). You can use qWarning() to send a message to the console. This technique should not be used to recover from coding errors. If a signal-slot connection fails because of an error in code, it should be fixed before it is released.

if(!connect(...)) {
   qWarning("Recovering from the failed connect()");
   // Add your code here to make sure that your app 
   // still works correctly, even though this connection 
   // has not been established.
}

You can also set the QT_FATAL_WARNINGS environment variable in your bar-descriptor.xml file. If the QT_FATAL_WARNINGS environment variable is set to 1, your app closes after qWarning() prints the warning message. For more information, see The bar-descriptor.xml file.

If you think that recovery is impossible because a successful connection is critical to your code, you can use qFatal() to close the app immediately. You can also consider adding additional code to clean up before closing the app.

if(!connect(...)) {

   // If your app uses shared files, write details about what
   // happened into a log file and ask users to send it to you.
   writeErrorLog();   
   
   // Make sure that you save as much user data as possible.
   saveOpenUserData();
   
   // Consider notifying users about the fatal error and 
   // warning them that the app will close now.
   qFatal("Cannot recover from the failed connect()");
}

Display Qt variables in the editor

In the Momentics IDE for BlackBerry, you can select an option to improve the display of Qt-based objects and variable values while you are debugging. This option lets you view the values of Qt objects, such as QVariant and QVariantMap, that you send to the debug console.

  1. In Windows and Linux, on the Window menu, click Preferences. In Mac OS, on the Momentics menu, click Preferences.
  2. Expand BlackBerry and click Debug.
  3. Select the Use advanced scripts to show variable values check box.
  4. Click Apply and then click OK.

For pointers, the address is printed and not dereferenced automatically. To see the value that the pointer points to, you need to dereference it manually in the Expressions view.

In Momentics IDE 2.1 and later, the advanced scripts that show variable values are enabled by default and for API level 10.1 and later.

Last modified: 2015-03-31



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus