суббота, 29 декабря 2012 г.

C++: remove useless warnings — убираем лишнюю диагностику

Компиляторы C++ дают диагностику двух видов — ошибки и предупреждения. Ошибки определены стандартом языка, а в предупреждения валится всё остальное.

В предупреждения могут выводиться реальные проблемы, приводящие к краху программы — скажем, неверная строка формата в функции printf. Но бывают и «неопасные» предупреждения — например, о неиспользуемой переменной. Исправить их сразу бывает невозможно, и тогда приходится уменьшать количество спама от компилятора.

Вот расстрельный список назойливых предупреждений:
  • Неиспользуемая локальная переменная, параметр функции, поле класса или функция.
  • Проблемы в заголовках сторонних библиотек, код которых трудно исправить
  • Компилятор в составе Visual Studio (для друзей MSVC) считает некошерными функции printf, scanf и так далее. Формально они плохи тем, что могут изменить переменную errno, которую потом ни один программист не проверяет. А если и проверит — может возникнуть состояние гонки между потоками, т.к. доступ к errno не атомарный. На деле никто и так не проверяет errno.
 Решить каждую из проблем можно силами компилятора:
  • GCC и совместимые с ним компиляторы (clang, intel compiler) принимают флаги -Wno-unused -Wno-uninitialized, устраняя самые частые и назойливые ложные срабатывания.
  • GCC и совместимые с ним компиляторы имеют специальную прагму, которая помещается в заголовок и глушит все предупреждения, возникшие в нём: #pragma GCC system_header. Аналогичное расширение есть у clang: #pragma clang system_header. Увы, инициатива здесь в руках разработчиков библиотеки.
  • Макрос _CRT_SECURE_NO_WARNINGS устранит предупреждения о printf, scanf и их друзьях. Его нужно объявить до той строки, где включён заголовок <stdio.h> — лучше всего в настройках проекта.

На примере QtCreator

Флаги — это хорошо, но хочется сделать всё не абы как, а в любимой среде разработки ;) В файл *.pro добавьте вот такие строки:
win32-msvc* {
    #Don't warn about sprintf, fopen etc being 'unsafe'
    DEFINES += _CRT_SECURE_NO_WARNINGS
}

QMAKE_CXXFLAGS_WARN_ON += -Wno-unused -Wno-uninitialized
Знатоки qmake, обратите внимание на вторую строчку: переменная QMAKE_CXXFLAGS здесь не используется. В QMAKE_CXXFLAGS нельзя помещать уровень оптимизации или уровень вывода предупреждений, потому что после них qmake запишет ещё два флага -O2 -Wall, и затрёт ваши старания.

P.S. Бонус для фанатов clang

Начиная с версии 3.2, clang умеет диагностировать ошибки в документации, то есть в doxygen. В драйвере компилятора за это отвечает флаг -Wdocumentation. В QtCreator (qmake) эта радость включается одной строчкой:
linux-clang:QMAKE_CXXFLAGS_WARN_ON += -Wdocumentation
Вот и всё =)

Комментариев нет:

Отправить комментарий