Я организую правила Klocwork и устраняю любые проблемы, обнаруженные при анализе stati c. Применено несколько правил, и в настоящее время у меня проблема с указанием литералов символов. Давайте рассмотрим этот пример:
for (const char* p = str; *p != '\0'; ++p)
Как видите, это l oop, повторяющаяся по C -String. Он используется для использования unordered_map строковых литералов constexpr. Измерения производительности показали, что хранение их как std :: string увеличивает использование памяти и влияет на производительность из-за накладных расходов. Поскольку содержимое этой карты является постоянным, я использую пользовательский функтор ha sh для C -Strings (опять же, чтобы избежать преобразований и копирования строки в std :: string просто для генерации ha sh). Простой ответ будет использовать std :: string_view, но он не доступен в этой среде. Таким образом, проблема исходит из самого условия. Условие должно проверять, завершается ли символ нулем.
Очевидно, что сначала я использовал !p
, так как по стандарту гарантируется, что завершение нуля преобразуется в ложь (независимо от того, что является реальным типом символа). Это приводит к ошибке AUTOSAR C ++ 14 (18-03) MISRA.STMT.COND.NOT_BOOLEAN
, которая переводится в « Условие оператора if или l oop имеет тип« 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('/')
, где я ищу указанный c символ, а не конкретное значение. Этот случай генерирует ту же ошибку, жалуясь, что я не указал суффикс. (uri - это std :: string)
Я полагаю, что это ложно-положительный результат реализации фильтра с ошибками Также кажется, что анализ stati c может быть неправильно настроен, так как символьные литералы считаются целочисленными только в C, а не в C ++.
В качестве примечания добавлю, что в первом примере, используя *p != char(0)
решил эту проблему, но это далеко от предпочтительного решения и может использоваться только с известным целочисленным значением символа, которое гораздо менее гибкое и подвержено ошибкам, чем использование литералов, поэтому я не собираюсь использовать этот обходной путь.
Что ваши мысли по этому поводу? Возможно, кто-то уже получил такую ошибку Klocwork и нашел решение, отличное от отключения правила или его подавления для каждого экземпляра буквенного символа. У меня уже есть список распространенных ложных срабатываний, которые довольно часто исходят из C ++ 11 и более новых стандартов, проверенных правилами, основанными на MISRA 2008 C ++.