Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top

Вебинар: Использование статических анализаторов кода при разработке безопасного ПО - 19.12

>
>
>
V3209. Unity Engine. Using await on 'Aw…
menu mobile close menu
Проверка проектов
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Микрооптимизации (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Реализовано по запросам пользователей (C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C++)
Стандарт OWASP (C#)
Проблемы при работе анализатора кода
Дополнительная информация
toggle menu Оглавление

V3209. Unity Engine. Using await on 'Awaitable' object more than once can lead to exception or deadlock, as such objects are returned to the pool after being awaited.

04 Дек 2024

Анализатор обнаружил более одного использования одного и того же 'UnityEngine.Awaitable' объекта с оператором 'await'. В целях оптимизации 'Awaitable' объекты хранятся в пуле-объектов. При await-вызове объект 'Awaitable' возвращается в пул. После этого при повторном применении 'await' к этому же объекту будет выброшено исключение, в некоторых случаях также возможна взаимная блокировка.

Рассмотрим синтетический пример:

async Awaitable<bool> AwaitableFoo() { .... }

async Awaitable ExampleFoo()
{
  Awaitable<bool> awaitable = AwaitableFoo();
  if (await awaitable)
  {
    var result = await awaitable;
    ....
  }
}

В этом коде будет выброшено исключение (или возникнет взаимная блокировка) при инициализации переменной 'result' значением, полученным с помощью 'await' вызова 'awaitable'. Это произойдёт из-за того, что ранее 'await' уже применялся к 'awaitable' в условии условной конструкции.

Чтобы обезопасить этот код, следует избегать записи 'Awaitable' в переменную. Вместо этого можно переиспользовать значение, полученное при await-вызове 'AwaitableFoo()':

async Awaitable<bool> AwaitableFoo() { .... }

async Awaitable ExampleFoo()
{
  bool value = await AwaitableFoo();
  
  if (value)
  {
    var result = value;
    ....
  }
}

Или повторно выполнять await-вызов непосредственно метода 'AwaitableFoo' там, где это требуется:

async Awaitable<bool> AwaitableFoo() { .... }

async Awaitable ExampleFoo()
{
  if (await AwaitableFoo())
  {
    var result = await AwaitableFoo();
    ....
  }
}

Такое решение также является корректным, ведь при каждом вызове 'AwaitableFoo()' будет возвращён новый объект 'Awaitable'.

Стоит отметить, что возможны и менее очевидные случаи возникновения проблемы. Например, когда повторный await-вызов значения 'Awaitable' происходит внутри другого метода, которому это значение было передано в качестве аргумента:

async Awaitable<bool> AwaitableFoo() { .... }

async Awaitable<Result> GetResult(Awaitable<bool> awaitable)
{
  if (await awaitable){ .... }                   // <=
  else { .... }
}

async Awaitable ExampleFoo()
{
  Awaitable<bool> awaitable = AwaitableFoo();

  if (await awaitable)                           // <=
  {
    ....
  }

  var result = await GetResult(awaitable);       // <=
}

Решения проблемы в таких случаях полностью аналогичны решениям, описанным ранее.

close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам