Методы отладки
Здесь представлены некоторые полезные советы, которые помогут вам отладить ваше Qt-приложение.
Настройка Qt для отладки
При настройке Qt для установки, можно убедиться, что он скомпилирован с включенными отладочными символами, что облегчит отслеживание ошибок в приложениях и библиотеках. Однако на некоторых платформах компиляция Qt в отладочном режиме приведет к увеличению размера приложений.
Отладка в macOS и Xcode
Отладка с/без фреймворков
Основные сведения об отладочных библиотеках и фреймворках можно найти на сайте developer.apple.com в: Технической заметке Apple TN2124.
При построении Qt фреймворки создаются по умолчанию, и внутри фреймворка вы найдёте как релизную, так и отладочную версии (например, QtCore и QtCore_debug). Если вы передадите флаг -no-framework при построении Qt, для каждой Qt библиотеки (например, libQtCore.4.dylib и libQtCore_debug.4.dylib) будут построены две dylib.
То, что происходит при линковке, зависит от того, используете ли вы фреймворки или нет. Мы не видим веских причин рекомендовать один вариант другому.
С фреймворками:
Поскольку релизные и отладочные библиотеки находятся внутри фреймворка, приложение просто ссылается на фреймворк. Затем, когда вы запускаете отладчик, вы получите либо релизную, либо отладочную версию в зависимости от того, установили ли вы DYLD_IMAGE_SUFFIX. Если вы не установите, вы получите релизную версию по умолчанию (т.е., без _debug). Если вы установите DYLD_IMAGE_SUFFIX=_debug, вы получите отладочную версию.
Без фреймворков:
Когда вы говорите qmake сгенерировать Makefile с отладочной конфигурацией, он будет ссылаться на _отладочную версию библиотек и сгенерирует отладочные символы для приложения. Запуск этой программы в GDB будет работать так же, как и на других платформах, и вы сможете отследить внутренние процессы Qt.
Командные строки, распознаваемые Qt
При запуске приложения Qt вы можете указать несколько командных строк, которые могут помочь при отладке. Они распознаются QApplication.
| Опция | Описание |
|---|---|
-nograb |
Приложение не должно захватывать мышь или клавиатуру. Эта опция устанавливается по умолчанию, когда программа запускается в gdb отладчике под Linux. |
-dograb |
Игнорировать все неявные или явные -nograb. -dograb имеет приоритет над -nograb, даже если -nograb стоит последним в командной строке. |
Переменные среды, распознаваемые Qt
Во время выполнения приложение Qt распознает множество переменных среды, некоторые из которых могут быть полезны для отладки:
| Переменная | Описание |
|---|---|
QT_DEBUG_PLUGINS |
Установите в ненулевое значение, чтобы Qt выводил диагностическую информацию о каждом загружаемом (C++) плагине. |
QML_IMPORT_TRACE |
Установите в ненулевое значение, чтобы QML выводил диагностическую информацию из механизма загрузки импорта. |
QT_HASH_SEED |
Установите целое числовое значение, чтобы отключить использование QHash и QSet с новой случайной сортировкой для каждого запуска приложения, что в некоторых случаях может затруднить тестирование и отладку. |
Сообщения об ошибках и отладке
Qt включает глобальные макросы для вывода предупреждений и отладочных сообщений. Вы можете использовать их для следующих целей:
- qDebug() используется для вывода пользовательских отладочных данных.
- qInfo() используется для информационных сообщений.
- qWarning() используется для отчётности о предупреждениях и восстанавливаемых ошибках в вашем приложении.
- qCritical() используется для вывода критических сообщений об ошибках и отчётности о системных ошибках.
- qFatal() используется для вывода сообщений о фатальных ошибках незадолго до выхода.
Если вы включите заголовок <QtDebug>, то макрос qDebug() также может использоваться в качестве потока вывода. Например:
qDebug() << "Widget" << widget << "at position" << widget->pos();
Реализация Qt этих макросов выводит в поток stderr под Unix/X11 и macOS. В Windows, если это консольное приложение, текст отправляется в консоль; в противном случае - в отладчик.
По умолчанию выводится только сообщение. Вы можете включить дополнительную информацию, установив переменную среды QT_MESSAGE_PATTERN. Например:
QT_MESSAGE_PATTERN="[%{type}] %{appname} (%{file}:%{line}) - %{message}" Формат описан в qSetMessagePattern(). Вы также можете установить собственный обработчик сообщений с помощью qInstallMessageHandler().
Если переменная среды QT_FATAL_WARNINGS установлена, qWarning() завершает работу после вывода предупреждающего сообщения. Это упрощает получение трассировки стека в отладчике.
qDebug(), qInfo() и qWarning() являются отладочными инструментами. Они могут быть исключены из компиляции с помощью определения QT_NO_DEBUG_OUTPUT, QT_NO_INFO_OUTPUT, или QT_NO_WARNING_OUTPUT во время компиляции.
Функции отладки QObject::dumpObjectTree() и QObject::dumpObjectInfo() часто полезны, когда приложение выглядит или действует странно. Более полезны, если использовать имена объектов, но часто полезны и без них.
Обеспечение поддержки оператора потока qDebug()
Вы можете реализовать оператор потока, используемый qDebug(), чтобы обеспечить поддержку отладки для ваших классов. Класс, который реализует оператор, — это QDebug. Используйте QDebugStateSaver для временного сохранения параметров форматирования потока. Используйте nospace() и манипуляторы QTextStream для дальнейшей настройки форматирования.
Вот пример класса, который представляет 2D координату.
QDebug operator<<(QDebug dbg, const Coordinate &c)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "(" << c.x() << ", " << c.y() << ")";
return dbg;
} Интеграция пользовательских типов с мета-объектной системой Qt подробно описана в документе Создание пользовательских типов Qt.
Макросы отладки
Заголовочный файл <QtGlobal> содержит некоторые макросы отладки и #define.
Три важных макроса:
-
Q_ASSERT(cond), где
cond— булево выражение, выводит предупреждение «ASSERT: 'cond' в файле xyz.cpp, строка 234» и завершает работу, еслиcondложно. -
Q_ASSERT_X(cond, where, what), где
cond— булево выражение,where— местоположение, иwhat— сообщение, выводит предупреждение: «Ошибка ASSERT вwhere: 'what', файл xyz.cpp, строка 234» и завершает работу, еслиcondложно. -
Q_CHECK_PTR(ptr), где
ptr— указатель. Выводит предупреждение «В файле xyz.cpp, строка 234: Недостаточно памяти» и завершает работу, еслиptrравен 0.
Эти макросы полезны для обнаружения ошибок в программе, например, так:
char *alloc(int size)
{
Q_ASSERT(size > 0);
char *ptr = new char[size];
Q_CHECK_PTR(ptr);
return ptr;
} Q_ASSERT(), Q_ASSERT_X() и Q_CHECK_PTR() не выполняют никаких действий, если QT_NO_DEBUG определено во время компиляции. По этой причине аргументы этих макросов не должны иметь побочных эффектов. Вот неправильное использование Q_CHECK_PTR():
char *alloc(int size)
{
char *ptr;
Q_CHECK_PTR(ptr = new char[size]); // WRONG
return ptr;
} Если этот код скомпилирован с определенным QT_NO_DEBUG, код в выражении Q_CHECK_PTR() не выполняется, и alloc возвращает неинициализированный указатель.
Библиотека Qt содержит сотни внутренних проверок, которые выведут сообщения об ошибках, когда будет обнаружена ошибка программирования. Поэтому мы рекомендуем использовать отладочную версию Qt при разработке Qt-приложений.
Распространённые ошибки
Существует одна ошибка, которая настолько распространена, что заслуживает упоминания здесь: если вы включаете макрос Q_OBJECT в объявлении класса и запускаете компилятор метаобъектов (moc), но забываете подключить сгенерированный метакомпилятором объект к исполняемому файлу, вы получите очень запутанные сообщения об ошибках. Любая ошибка линковки, жалующаяся на отсутствие moc, vtbl, _vtbl или подобного, скорее всего, является результатом этой проблемы.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.11/debug.html