Методы отладки
Здесь представлены некоторые полезные подсказки, которые помогут вам отладить ваше программное обеспечение на основе Qt.
Настройка Qt для отладки
При настройке Qt для установки, можно обеспечить, что он скомпилирован с включенными символами отладки, которые могут облегчить отслеживание ошибок в приложениях и библиотеках. Однако на некоторых платформах компиляция Qt в режиме отладки приведет к увеличению размера приложений.
Отладка в macOS и Xcode
Отладка с/без фреймворков
Основные сведения о библиотеках отладки и фреймворках можно найти на сайте developer.apple.com в: Техническая заметка Apple TN2124.
При построении Qt фреймворки создаются по умолчанию, и внутри фреймворка вы найдете как релизную, так и отладочную версии (например, QtCore и QtCore_debug). Если вы передадите флаг -no-framework при построении Qt, для каждой библиотеки Qt будут созданы две dylib (например, libQtCore.4.dylib и libQtCore_debug.4.dylib).
То, что происходит при линковке, зависит от того, используете ли вы фреймворки или нет. У нас нет убедительных причин рекомендовать один вариант над другим.
С фреймворками:
Поскольку релизные и отладочные библиотеки находятся внутри фреймворка, приложение просто ссылается на фреймворк. Затем, при запуске в отладчике, вы получите либо релизную, либо отладочную версию, в зависимости от того, установили ли вы DYLD_IMAGE_SUFFIX. Если вы не установите его, по умолчанию используется релизная версия (т.е., без _debug). Если вы установите DYLD_IMAGE_SUFFIX=_debug, вы получите отладочную версию.
Без фреймворков:
Когда вы укажете qmake сгенерировать Makefile с конфигурацией отладки, он будет ссылаться на _debug версию библиотек и сгенерирует символы отладки для приложения. Запуск этой программы в 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— сообщение, выводит предупреждение: "Ошибка проверки в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, __vtbl или подобного, вероятно, является следствием этой проблемы.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.6/debug.html