为什么代码审查不错,但还不够

image1.png


代码审查绝对是必要且有用的。这是一个传递知识,培训,控制任务,提高代码的质量和设计并修复错误的机会。此外,您会注意到与所使用的体系结构和算法相关的高级错误。总的来说,一切都很好,但是人们很快就会厌倦。因此,静态分析是对检查的极佳补充,并有助于识别各种肉眼看不到的错误和误印。让我们看一个有关此主题的好例子。



尝试查找从structopt库获取的功能代码中的错误



static inline bool is_valid_number(const std::string &input) {
  if (is_binary_notation(input) ||
      is_hex_notation(input) ||
      is_octal_notation(input)) {
    return true;
  }

  if (input.empty()) {
    return false;
  }

  std::size_t i = 0, j = input.length() - 1;

  // Handling whitespaces
  while (i < input.length() && input[i] == ' ')
    i++;
  while (input[j] == ' ')
    j--;

  if (i > j)
    return false;

  // if string is of length 1 and the only
  // character is not a digit
  if (i == j && !(input[i] >= '0' && input[i] <= '9'))
    return false;

  // If the 1st char is not '+', '-', '.' or digit
  if (input[i] != '.' && input[i] != '+' && input[i] != '-' &&
      !(input[i] >= '0' && input[i] <= '9'))
    return false;

  // To check if a '.' or 'e' is found in given
  // string. We use this flag to make sure that
  // either of them appear only once.
  bool dot_or_exp = false;

  for (; i <= j; i++) {
    // If any of the char does not belong to
    // {digit, +, -, ., e}
    if (input[i] != 'e' && input[i] != '.' &&
        input[i] != '+' && input[i] != '-' &&
        !(input[i] >= '0' && input[i] <= '9'))
      return false;

    if (input[i] == '.') {
      // checks if the char 'e' has already
      // occurred before '.' If yes, return false;.
      if (dot_or_exp == true)
        return false;

      // If '.' is the last character.
      if (i + 1 > input.length())
        return false;

      // if '.' is not followed by a digit.
      if (!(input[i + 1] >= '0' && input[i + 1] <= '9'))
        return false;
    }

    else if (input[i] == 'e') {
      // set dot_or_exp = 1 when e is encountered.
      dot_or_exp = true;

      // if there is no digit before 'e'.
      if (!(input[i - 1] >= '0' && input[i - 1] <= '9'))
        return false;

      // If 'e' is the last Character
      if (i + 1 > input.length())
        return false;

      // if e is not followed either by
      // '+', '-' or a digit
      if (input[i + 1] != '+' && input[i + 1] != '-' &&
          (input[i + 1] >= '0' && input[i] <= '9'))
        return false;
    }
  }

  /* If the string skips all above cases, then
  it is numeric*/
  return true;
}


为了不立即误读答​​案,我将添加一张图片。



image2.png


我不知道您是否发现错误。即使找到了它,您也一定会同意,找到这样的错字并不容易。此外,您知道函数存在错误。如果您不知道,那么很难使您仔细阅读并检查所有这些代码。



在这种情况下,静态代码分析器将完美地补充经典代码审查。分析仪不会感到疲劳,并将彻底检查整个代码。结果,PVS-Studio分析仪发现此功能异常并发出警告:



V560条件表达式的一部分始终为false:输入[i] <='9'。 structopt.hpp 1870



对于那些没有注意到该错误的人,我将给出一个解释。最重要的事情:



else if (input[i] == 'e') {
  ....
  if (input[i + 1] != '+' && input[i + 1] != '-' &&
      (input[i + 1] >= '0' && input[i] <= '9'))
      return false;
}


上面的条件检查第i个元素是否为字母“ e”。因此,后面的检查输入[i] <='9'没有意义。第二次检查的结果始终为假,这是静态分析工具所警告的。错误的原因很简单:该人匆忙密封自己,忘记写+1。



实际上,事实证明该功能无法完成检查输入数字正确性的工作。正确的选项:



else if (input[i] == 'e') {
  ....
  if (input[i + 1] != '+' && input[i + 1] != '-' &&
      (input[i + 1] >= '0' && input[i + 1] <= '9'))
      return false;
}


一个有趣的观察。该错误可以看作是“最后一行效果的变体错误是在该函数的最后状态。最后,程序员的注意力减弱了,他犯了这个微妙的错误。





如果您喜欢有关最后一行效果的文章,那么我建议您阅读其他类似的观察文章:0-1-2memsetcomparisons



大家再见 我喜欢那些独自发现错误的人。



All Articles