我正在组织 Klocwork 规则并清除静态分析发现的任何问题。应用了多个规则,目前我在指定字符文字时遇到问题。让我们考虑这个例子:
for (const char* p = str; *p != '\0'; ++p)
如您所见,这是对 C-String 的循环迭代。它用于利用 constexpr 字符串文字的 unordered_map。性能测量证明,将它们存储为 std::string 会增加内存使用并由于开销而影响性能。由于此地图内容是恒定的,我正在使用 C-Strings 的自定义哈希函子(再次,以避免转换并将字符串复制到 std::string 只是为了生成哈希)。简单的答案是使用 std::string_view 但在此环境中不可用。所以问题来自条件本身。条件应检查字符是否以空值结尾。
显然,起初我使用!p
它,因为标准保证终止 null 解析为 false(无论 char 的真实类型是什么)。它会导致 AUTOSAR C++14 (18-03) 错误MISRA.STMT.COND.NOT_BOOLEAN
,转换为“ if 或循环语句的条件具有类型 'char' 而不是 'boolean' ”。
好的,然后我将其更改为显式比较p != 0
,结果证明是MISRA.CHAR.NOT_CHARACTER
违规行为,即“ 'char' is used for non-character value ”。
同样,这是有效的一点,因为我将 char 与 int 进行比较,但 char 既不是 int 也不是 unsigned int。因此我将其更改为*p != '\0'
应该直接转换为空字符。这反过来又给出了MISRA.LITERAL.UNSIGNED.SUFFIX
违规,即“无符号整数文字 ''\0'' without the 'U' suffix ”。现在我很惊讶。即使 char 在一个编译器中被认为是无符号的,也不能保证它是有符号的或无符号的,所以我不能将它硬编码为任何符号。甚至没有提到似乎没有办法为字符文字指定后缀。在我看来,它已经误报为'\0'
IS char 类型,不需要任何进一步的转换或强制转换。这显示了更明显的语法问题,例如uri.find_last_of('/')
我正在寻找特定的字符,而不是特定的价值。这种情况会产生同样的错误,抱怨我没有指定后缀。(uri 是 std::string)
我的猜测是,这是错误过滤器实现的误报。此外,似乎静态分析可能被错误配置,因为字符文字仅在 C 中被认为是整数,而不是在 C++ 中。
作为旁注,我将在第一个示例中补充说,使用*p != char(0)
解决了这个问题,但这远非首选解决方案,并且只能与已知的字符整数值一起使用,这远不如使用文字灵活且容易出错,因此我不会使用此解决方法。
你对这个问题有什么看法?也许其他人已经遇到了这样的 Klocwork 错误并找到了解决方案,而不是为每个文字字符实例禁用规则或抑制它。我已经有了我的常见误报列表,这些误报通常来自 C++11 和更新的标准,由基于 MISRA 2008 C++ 的规则检查。