Я организую правила Klocwork и устраняю любые проблемы, обнаруженные статическим анализом. Применяется несколько правил, и в настоящее время у меня проблема с указанием символьных литералов. Рассмотрим этот пример:
for (const char* p = str; *p != '\0'; ++p)
Как видите, это цикл, повторяющий C-String. Он используется для использования unordered_map строковых литералов constexpr. Измерения производительности показали, что их хранение как std :: string увеличивает использование памяти и влияет на производительность из-за накладных расходов. Поскольку содержимое этой карты является постоянным, я использую пользовательский хеш-функтор для C-строк (опять же, чтобы избежать преобразований и копирования строки в std :: string только для генерации хеша). Простой ответ - использовать std :: string_view, но он недоступен в этой среде. Итак, проблема исходит из самого состояния. Условие должно проверять, заканчивается ли символ нулем.
Очевидно, сначала я использовал !p
, поскольку стандарт гарантирует, что завершение null преобразуется в false (независимо от того, какой тип символа является реальным). Это приводит к ошибке AUTOSAR C ++ 14 (18-03) MISRA.STMT.COND.NOT_BOOLEAN
, которая переводится как «Условие оператора if или цикла имеет тип 'char' вместо 'boolean'».
Хорошо, тогда я изменил это на явное сравнение p != 0
, и оказалось, что это MISRA.CHAR.NOT_CHARACTER
нарушение, то есть «'char' используется для несимвольного значения».
Опять же, это верный момент, поскольку я сравниваю char с int, но char не является ни int, ни unsigned int. Поэтому я изменил его на *p != '\0'
, который должен напрямую переводиться в нулевой символ. Это, в свою очередь, дает MISRA.LITERAL.UNSIGNED.SUFFIX
нарушение, которое представляет собой «Целочисленный литерал без знака '' \ 0 '» без суффикса «U» ». Теперь я удивлен. Даже если char считается беззнаковым в одном компиляторе, не гарантируется, что он будет ни подписанным, ни беззнаковым, поэтому я не могу жестко закодировать его для любого знака. Не говоря уже о том, что, похоже, нет способа указать суффикс для символьных литералов. На мой взгляд, это уже ложное срабатывание, поскольку тип '\0'
IS char и не требует дальнейшего преобразования или преобразования. Это показывает еще более заметную проблему с синтаксисом типа uri.find_last_of('/')
, когда я ищу конкретный символ, а не конкретное значение. В этом случае возникает та же ошибка, с жалобой на то, что я не указал суффикс. (uri - это std :: string)
Я предполагаю, что это ложное срабатывание из-за ошибочной реализации фильтра. Также кажется, что статический анализ может быть неправильно настроен, поскольку символьные литералы считаются целыми только в C, а не в C ++.
В качестве побочного примечания я добавлю, что в первом примере с использованием *p != char(0)
эта проблема решена, но это далеко не предпочтительное решение и может использоваться только с известным целочисленным значением символа, которое гораздо менее гибко и подвержено ошибкам, чем использование литералов, поэтому я не собираюсь чтобы использовать этот обходной путь.
Что вы думаете об этой проблеме? Возможно, кто-то уже получил такую ошибку Klocwork и нашел решение, кроме отключения правила или подавления его для каждого экземпляра буквального символа. У меня уже есть список распространенных ложных срабатываний, которые довольно часто возникают из-за стандартов C ++ 11 и более новых, проверенных по правилам, основанным на MISRA 2008 C ++.