﻿# V2609\. MISRA\. There should be no occurrence of undefined or critical unspecified behaviour\.

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

Это правило актуально только для C\. Если в программе возникает неопределённое поведение, то у программиста нет никаких гарантий относительно её исполнения\. Такое поведение недопустимо\.

Если в программе возникает критическое неуточнённое поведение, это означает, что в зависимости от компилятора и его конфигурации возможно различное исполнение кода\. Такое поведение также недопустимо\.

В общем случае нельзя сказать, может ли в программе произойти неопределённое или неуточнённое поведение или нет\. Не все случаи неопределённого поведения можно распознать\. Поэтому нет и не может быть алгоритма, который гарантировал бы отсутствие неопределённого или неуточнённого поведения в конкретной программе\.

Однако существует множество ситуаций, которые могут привести к неопределённому или критическому неуточнённому поведению и которые можно распознать алгоритмически\. Рассмотрим некоторые из таких случаев\.

Часто можно определить потенциальное разыменование нулевого указателя\. Рассмотрим следующий фрагмент кода:

```cpp
void foo()
{
  int len = GetLen();
  char *str = (char *) malloc(mlen + 1);
  str[len] = '\0';
}
```

При выполнении этого фрагмента кода может произойти разыменование нулевого указателя\. Если функция 'malloc' не сможет выделить память, то она запишет 'nullptr' в переменную 'str'\. Тогда в выражении 'str\[len\]' произойдет разыменование 'nullptr', что является неопределенным поведением\. Анализатор выдаст следующее предупреждение:

V2609 Undefined behaviour should not occur\. There might be dereferencing of a potential null pointer 'str'\. Check lines: 4, 5\.

На первый взгляд может показаться, что подобные ошибки сразу приведут к аварийному завершению программы\. Во многих операционных системах первые килобайты адресного пространства защищены от записи\. И при попытке записи в них возникнет исключение/сигнал\. А значит, ошибка не является критичной\. Это совсем не так\.

* В случае, если переменная 'len' имеет большое значение, выражение 'str\[len\]' может ссылаться на достаточно удаленные ячейки памяти доступные для записи\. Запись туда нуля приведет к непредсказуемым последствиям\. Т\.е\. к тому самому неопределенному поведению\.
* Остановка программы — это тоже критическая ошибка для некоторых приложений\.
* В некоторых микроконтроллерах младшие адреса адресного пространства не защищены от записи, и запись по нулевому указателю никак не будет отловлена операционной системой\. Собственно, часто никакой операционной системы и нет\.

Более подробно все это рассмотрено в статье "[Почему важно проверять, что вернула функция malloc](https://pvs-studio.ru/ru/blog/posts/cpp/0558/)"\.

Еще одной ситуацией, которую можно распознать алгоритмически, является модификация переменной между двумя точками следования и неоднократное обращение к ней\.

Рассмотрим следующий фрагмент кода:

```cpp
void foo()
{
  int *ptr;
  ....
  *ptr++ = *(ptr + 1);
}
```

Здесь предполагается, что сначала произойдет увеличение указателя 'ptr' на 1\. Затем произойдет вычисление выражения 'ptr \+ 1', и использоваться будет уже новое значение 'ptr'\.

Однако такое предположение программиста неверно\. Дело в том, что между двумя точками следования происходит два обращения к переменной 'ptr', одно из которых модифицирует ее значение\. В таком случае поведение программы неопределенное\.

Анализатор выдаст следующее предупреждение:

V2609 Undefined behaviour should not occur\. The 'bufl' variable is modified while being used twice between sequence points\.

Также можно определить [некорректное использование битовых операторов сдвига](https://pvs-studio.ru/ru/blog/posts/cpp/0142/)\. Рассмотрим следующий код:

```cpp
void foo()
{
  int delta = -2;
  ....
  int expr = DoSomeCalculations();
  expr <<= delta;
}
```

Здесь переменная 'expr' сдвигается влево на \-2 бита\. Сдвиг на отрицательное число битов является некорректной операцией и приводит к неопределенному поведению\.