Обе стороны имеют побочные эффекты?

Я выполнил статический анализ кода для MISRA 2004 и MISRA 2012 для следующего кода C:

BOOL_TYPE Strings_Are_Equal(const char *s1, const char *s2)
{
  BOOL_TYPE result = True;
  const char *str1 = s1;
  const char *str2 = s2;

  if (NULL == s1 || NULL == s2)
  {
    result = False;
  }
  else if (strlen(s1) != strlen(s2))
  {
    result = False;
  }
  else
  {
    while (*str1 != 0)
    {
      if(tolower(*str1++) != tolower(*str2++))
      {
        result = False;
        break;
      }
    }
  }

  return result;
}

и получил следующие результаты из отчетов PC-lint: введите здесь описание изображения

Может кто-нибудь объяснить, как код в строке 58 и 66 страдает от побочных эффектов и как мне его исправить?


person Akay    schedule 28.06.2016    source источник


Ответы (2)


Вызов функции может вызвать побочный эффект при использовании формального определения стандарта C.

В конкретном случае strlen(s1) != strlen(s2) внутри этих функций нет ничего, что могло бы причинить вред. Не имеет смысла реализовывать их, например, с внутренними static переменными. Но если бы такие внутренние переменные присутствовали, порядок оценки мог бы давать разные результаты в зависимости от того, какой вызов функции был выполнен первым. Это, вероятно, обоснование предупреждения.

В случае tolower(*str1++) != tolower(*str2++) есть как два побочных эффекта вызова функции, так и два побочных эффекта присваивания переменных от операторов ++, всего 4 в одном выражении. Несмотря на то, что этот конкретный случай безопасен, такой код опасен, так как он может зависеть от порядка вычисления или даже оказаться полностью неупорядоченным (например, i=i++;), что было бы серьезной ошибкой.

Решите это, сохранив результаты функции во временных переменных. И никогда не смешивайте ++ с другими операторами, потому что это опасно, бессмысленно и запрещено другим правилом MISRA:

MISRA-C:2004 Правило 12.13

Операторы инкремента (++) и декремента (--) не следует смешивать с другими операторами в выражении.

person Lundin    schedule 28.06.2016
comment
Имхо правильный ответ. Я дал вам голос, так как вы указали, что я забыл сначала. (Должно быть, это было голосование за рулем) - person 2501; 28.06.2016
comment
Причина отрицательного голосования? Отсутствие кавычек по правилам MISRA и стандарту C? Не могу найти ошибки в ответе. - person Lundin; 28.06.2016

В качестве дополнения к отличному ответу Лундина подход, совместимый с MISRA, будет следующим:

    while (*str1 != 0)
    {
      // Condition should be a single sequence point
      // ... with no side effects
      if ( tolower(*str1) != tolower(*str2) )
      {
        result = false;
        break;
      }

      // Now increment pointers
      str1++;
      str2++;
    }

Таким образом, у вас есть четкое различие между вашими точками последовательности.

person Andrew    schedule 05.07.2016