Как стать автором
Обновить

Сообщения об ошибках + templates: несколько простых советов

Время на прочтение3 мин
Количество просмотров796

Немножко лирики


Должен сразу предупредить, что эта тема вряд ли пригодится программистам, которые дружат с С++ давно и прочно. Моя цель — немного помочь тем, кто при использовании чужих библиотек с большим количеством template'ов впадает в легкую панику при виде сообщений об ошибках. Как показывает практика, зачастую всё совсем не так страшно, как выглядит и вполне помогает понять, в чём проблема.

Идея написать подобную заметку возникла в процессе написания программы, активно использующей Boost::Spirit2 — сложная грамматика, обилие semantic action, создание AST через attribute value и тому подобные радости. В какой-то момент я обратил внимание на то, что для исправления многих ошибок мне хватает одной-двух минут, в то время как в начале работы над проектом в аналогичных случаях на разбор ситуации могло уходить до часа.

Всё написано исходя из работы с gcc, но, думаю, провести аналогию с испольуземым %compiler_name& будет не сложно.

Самое время делиться!

Что же нам поможет?


  • Fatal Errors

    Прежде всего, стоит включить опцию компилятора, делающую любую ошибку фатальной. В случае gcc это -Wfatal-errors. В случае метапрограммирования изучение более одного сообщения об ошибке за раз всё равно не имеет особого смысла — скорее всего исправление первой из них повлияет и на множество последующих. А стена текста станет куда ниже.

  • Зрить в корень

    Если присмотреться, то окажется, что сообщения о template ошибках имеют примерно такую структуру:

    In file included from %header path%,
                     from %header path%,
                     ...
                     from %source filename%:
    %header path%: In function '%full name%'
    %header path%: instantiated from '%full name%'
    ...
    %source filename%: instantiated from %full name%
    ...
    %header path%: error: %error description%

    А если присмотреться ещё внимательнее, то окажется, что блок с «instantiated from», проходящий по всей иерархии включаемых заголовочных файлов — самый объемный и самый бесполезный. Едва ли нас часто интересует, какими окольными путями дело дошло от вызова библиотечной функции до ошибки. Зато интересует, что это за ошибка и какая именно строчка нашего кода (блок «instantiated from» для %source filename%) её породила.

    А это совсем немного и вполне читаемо. Иногда достаточно просто взглянуть на строчку в коде, из-за которой всё понеслось и сразу становится видна глупейшая опечатка, вылившаяся в подобное непотребство. Не придётся даже читать сообщение об ошибке, которой в такой ситуации всё равно ничего толкового не скажет.

  • typedef есть typedef

    Удобно иметь под рукой набор find-and-replace правил для основных typedef типов, используемых в проблемном коде. Даже короткий std::basic_string<char> куда лучше смотрится в виде std::string, что уж говорить о векторах списков пар векторов и очередей. Например, в vim можно написать простой replace-скрипт, через который прогонять каждый раз сообщение об ошибке, если оно длиннее пары строк, и приводить в читаемый вид.

  • Чтение исходников

    Если ошибка в template коде, то мы практически в шаге от исходников. Когда уже нет ни малейших идей, в чём может быть проблема, стоит открыть ту часть заголовочного файла библиотеки, на которую жалуется компилятор ( %header path%: error: ) и познакомиться поближе. Как правило, даже в очень жестоких boost библиотеках небольшие кусочки по отдельности читаемы и понятны.


После того, как я перестал в ужасе смотреть на очередное сообщение об ошибке, а стал сразу же препарировать этими простыми способами, время отладки сократилось на порядок. Чего и вам желаю.

А какие трюки используете вы? Был бы рад прочитать в комментариях советы по теме. Предлагаю бороться с недостатками дизайна С++ коллективно.
Теги:
Хабы:
+2
Комментарии6

Публикации

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн