﻿# V2656\. MISRA\. Standard Library function 'memcmp' should not be used to compare null\-terminated strings\.

Диагностическое правило основано на руководстве [MISRA](https://misra.org.uk/) \(Motor Industry Software Reliability Association\) по разработке программного обеспечения\.

Правило актуально только для языка C\.

Функция стандартной библиотеки [`memcmp`](https://en.cppreference.com/w/c/string/byte/memcmp) не должна быть использована для сравнения [`null`\-терминированных строк](https://en.cppreference.com/w/c/string/byte.html)\.

В рамках текущего правила `null`\-терминированные строки – это:

* [строковые литералы](https://en.cppreference.com/w/c/language/string_literal.html);
* массивы [сущностно\-символьного типа](https://pvs-studio.ru/ru/blog/terms/7007/), содержащие [терминальный ноль](https://pvs-studio.ru/ru/blog/terms/0088/) \(`\0`\)\.

Функция `memcmp` выполняет побайтовое сравнение двух последовательных участков памяти\. При сравнении строк возможна ситуация, когда фактический размер каждой строки \(все символы до терминального нуля\) меньше, чем выделенный буфер\. Полное сравнение таких буферов через функцию `memcmp` может привести к неожиданным результатам\. Например, две логически одинаковые строки могут считаться различными\. Это происходит из\-за того, что символы после терминального нуля будут участвовать в сравнении, даже если они не являются частью строки\.

Рассмотрим пример:

```cpp
static _Bool FilesHaveSameContent(const FILE *lhs,
                                  const FILE *rhs)
{
  if (!lhs || !rhs) return false;

  char l_buf[256];
  char r_buf[256];

  while (fgets(l_buf, sizeof(l_buf), lhs)
      && fgets(r_buf, sizeof(r_buf), rhs))
  {
    if (memcmp(l_buf, r_buf, sizeof(l_buf)) != 0) // <=
    {
      return false;
    }
  }

  return feof(lhs) && feof(rhs);
}
```

Функция `FilesHaveSameContent` используется для построчного сравнения файлов\. Содержимое из файлов считывается в соответствующие буферы `l_buf` и `r_buf`, размером 256 байтов каждый, с помощью функции [`fgets`](https://en.cppreference.com/w/c/io/fgets)\. Затем с помощью функции `memcmp` происходит их побайтовое сравнение\.

Функция `fgets` читает указанное количество символов и сохраняет их в буфер\. Чтение останавливается, если встречается символ переноса строки или конец файла\. Если чтение прошло успешно, то за последним прочитанным символом из файла в буфере будет записан терминальный ноль\.

Таким образом, если из двух **одинаковых файлов** считались строки размером менее 255 байт, то их сравнение может дать неправильный результат, поскольку символы после терминального нуля будут не инициализированы\.

Для исправления проблемы следует заменить функцию `memcmp` на [`strcmp`](https://en.cppreference.com/w/c/string/byte/strcmp) или [`strncmp`](https://en.cppreference.com/w/c/string/byte/strncmp.html):

```cpp
if (strcmp(l_buf, r_buf) != 0)
{
  return false;
}
```