>
>
>
V1036. Potentially unsafe double-checke…


V1036. Potentially unsafe double-checked locking.

Анализатор обнаружил потенциальную ошибку, связанную с небезопасным использованием паттерна "блокировки с двойной проверкой" (double checked locking). Блокировка с двойной проверкой - это паттерн, предназначенный для уменьшения накладных расходов получения блокировки. Сначала проверяется условие блокировки без синхронизации. И только если условие выполняется, поток попытается получить блокировку. Таким образом, блокировка будет выполнена только если она действительно была необходима.

Рассмотрим пример с ошибкой:

static std::mutex mtx;
class TestClass
{
public:
  void Initialize()
  {
    if (!initialized) 
    {
      std::lock_guard lock(mtx);
      if (!initialized) // <=
      {
        resource = new SomeType();
        initialized = true;
      }
    }
  }
  /* .... */

  private:
    bool initialized = false;
    SomeType *resource = nullptr;
  };
}

В этом примере, оптимизация компилятором порядка назначений переменных 'resource' и 'initialized' может привести к ошибке. Т.е. в начале переменной 'initialized' будет присвоено значение 'true', а уже потом будет выделена память под объект типа 'SomeType' и проинициализирована переменная 'resource'.

Такая перестановка может привести к ошибке при доступе к объекту из параллельного потока. Получается, что переменная 'resource' будет еще не проинициализирована, а флаг 'intialized' уже будет выставлен в 'true'.

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

Дополнительные ссылки:

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

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