﻿# Исследование COVID\-19 и неинициализированная переменная

Существует открытый проект COVID\-19 CovidSim Model, написанный на языке C\+\+\. Существует статический анализатор кода PVS\-Studio, который умеет хорошо находить ошибки\. Однажды они встретились\. Познайте хрупкость алгоритмов математического моделирования и почему нужно прикладывать максимум усилий к качеству программного кода\.

![0796_covid_sim_ru/image1.png](https://import.viva64.com/docx/blog/0796_covid_sim_ru/image1.png)

На днях мне понадобилось кое\-что найти на GitHub, что является началом этой маленькой истории\. Изучая результаты поиска, я случайно набрёл на проект [COVID\-19 CovidSim Model](https://github.com/mrc-ide/covid-sim)\. Недолго думая, я решил проверить его с помощью анализатора PVS\-Studio\.

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

```cpp
void CalcLikelihood(int run, std::string const& DataFile,
                    std::string const& OutFileBase)
{
  ....
  double m = Data[row][col]; // numerator
  double N = Data[row][col + 1]; // denominator
  double ModelValue;
  // loop over all days of infection up to day of sample
  for (int k = offset; k < day; k++)
  {
    // add P1 to P2 to prevent degeneracy
    double prob_seroconvert = P.SeroConvMaxSens *
      (1.0 - 0.5 * ((exp(-((double)(_I64(day) - k)) * P.SeroConvP1) + 1.0) *
      exp(-((double)(_I64(day) - k)) * P.SeroConvP2)));
    ModelValue += c * TimeSeries[k - offset].incI * prob_seroconvert;
  }
  ModelValue += c * TimeSeries[day - offset].S * (1.0 - P.SeroConvSpec);
  ModelValue /= ((double)P.PopSize);
  // subtract saturated likelihood
  LL += m * log((ModelValue + 1e-20) / (m / N + 1e-20)) +
        (N - m) * log((1.0 - ModelValue + 1e-20) / (1.0 - m / N + 1e-20));
  ....
}
```

Серьёзный научный код\. Что\-то считается\. Формулы\. Выглядит всё умно и обстоятельно\.

Вот только все эти вычисления разбиваются о человеческую невнимательность\. Хорошо, что на помощь может прийти анализатор кода PVS\-Studio и указать на баг: V614 \[CWE\-457\] Uninitialized variable 'ModelValue' used\. CovidSim\.cpp 5412

И действительно, посмотрим внимательнее на это:

```cpp
double ModelValue;
for (int k = offset; k < day; k++)
{
  double prob_seroconvert = ....;
  ModelValue += c * TimeSeries[k - offset].incI * prob_seroconvert;
}
```

Перед нами простая и одновременно страшная ошибка: неинициализированная переменная\. Этот алгоритм может насчитать всё что угодно\.

Собственно, на этом всё\. Пояснять тут нечего\. Остаётся только вновь напомнить, что разработчики научных библиотек и научных приложений должны прикладывать дополнительные усилия для обеспечения качества кода\. Падение обыкновенного приложения, скорее всего, будет стоить намного дешевле, чем использование некорректных результатов вычислений в научных, медицинских и прочих целях\.

Это уже не первая наша статья на эту тему:

* [Анализ кода ROOT \- фреймворка для анализа данных научных исследований](https://pvs-studio.ru/ru/blog/posts/cpp/0682/)
* [NCBI Genome Workbench: научные исследования под угрозой](https://pvs-studio.ru/ru/blog/posts/cpp/0591/)
* [Большой Калькулятор выходит из\-под контроля](https://pvs-studio.ru/ru/blog/posts/cpp/0212/)

Используйте статический анализатор кода [PVS\-Studio](https://pvs-studio.ru/ru/pvs-studio/)\! Польза от своевременно найденных ошибок может быть колоссальной\. Спасибо за внимание\.