Unicorn with delicious cookie
Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
>
>
>
V3110. Possible infinite recursion.
menu mobile close menu
Проверка проектов
Дополнительная информация
toggle menu Оглавление

V3110. Possible infinite recursion.

09 Авг 2016

Анализатор обнаружил, что может возникать бесконечная рекурсия. Скорее всего это приведет к переполнению стека вызовов и возникновению исключения Stack Overflow.

Рассмотрим пример. Пусть у нас имеется свойство 'MyProperty' и поле '_myProperty', связанное с ним. Из-за опечатки можно допустить следующую ошибку:

private string _myProperty;
public string MyProperty 
{
  get { return MyProperty; } // <=
  set { _myProperty = value; }
}

При указании возвращаемого значения в методе доступа свойства, вместо поля '_myProperty' было указано свойство 'MyProperty', что приводится к возникновению бесконечной рекурсии при получении значения у свойства. Корректный код должен выглядеть так:

private string _myProperty;
public string MyProperty 
{
  get { return _myProperty; }
  set { _myProperty = value; }
}

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

class Node 
{
  Node parent;
  public void Foo() 
  {
    // some code
    parent.Foo(); // <=
  }
}

Вероятнее всего программист хотел рекурсивно обойти все поля 'parent', но не предусмотрел условия выхода из рекурсии. Эта ситуация более интересная: здесь может возникнуть не только переполнение стека, но и доступ по нулевой ссылке, когда мы дойдём до самой верхней родительской сущности. Корректный код мог бы выглядеть так:

class Node 
{
  Node parent;
  public void Foo() 
  {
    // some code
    if (parent != null)
      parent.Foo();
  }
}

Рассмотрим третий пример. Пусть у нас имеется метод с конструкцией 'try - catch - finally'.

void Foo()
{
  try
  {
    // some code;
    return;
  }
  finally
  {
    Foo(); // <=
  }
}

Вероятнее всего программист не учел, что блок 'finally' будет выполнен как в случае возникновения исключения внутри блока 'try', так и в случае выхода из метода оператором 'return'. Таким образом блок 'finally' всегда будет выполнять рекурсивный вызов метода 'Foo'. Для корректного выполнения рекурсии необходимо реализовать условие перед выполнением метода. К примеру корректный код мог бы выглядеть так:

void Foo()
{
  try
  {
    // some code;
    return;
  }
  finally
  {
    if (condition)
      Foo();
  }
}

Данная диагностика классифицируется как:

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V3110.