# V712. Compiler may optimize out this loop or make it infinite. Use volatile variable(s) or synchronization primitives to avoid this.

Анализатор обнаружил в коде цикл с пустым телом, который может быть превращён компилятором после оптимизации в вечный цикл или убран из кода программы. Чаще всего подобные циклы используются для ожидания какого-либо события извне.

Пример:

    bool AllThreadsCompleted = false; // Глобальная переменная
    ....
    while (!AllThreadsCompleted);

В данной ситуации оптимизирующий компилятор сделает цикл вечным. Посмотрим на ассемблерный код из Debug-версии:

    ; 8    :   AllThreadsCompleted = false;

        mov BYTE PTR ?AllThreadsCompleted@@3_NA, 0
         ; AllThreadsCompleted
    $LN2@main:

    ; 9    :
    ; 10   :   while (!AllThreadsCompleted);

        movzx eax, BYTE PTR ?AllThreadsCompleted@@3_NA
         ; AllThreadsCompleted
         test eax, eax
         jne SHORT $LN1@main
         jmp SHORT $LN2@main
    $LN1@main:

В данном случае проверка, очевидно, присутствует. Теперь же обратимся к Release-версии:

    $LL2@main:

    ; 8    :   AllThreadsCompleted = false;
    ; 9    :
    ; 10   :   while (!AllThreadsCompleted);

        jmp SHORT $LL2@main

В Release-версии переход был оптимизирован в безусловный. Из-за подобного различия Debug-версии и Release-версии могут возникать сложные и трудно детектируемые ошибки.

Путей корректировки данной ситуации несколько. Если эта переменная и впрямь используется для контроля логики многопоточной программы, то лучше использовать средства синхронизации операционной системы, такие как мьютексы и семафоры. Другим вариантом исправления может стать добавление модификатора 'volatile' к объявлению переменной, запрещающему оптимизацию:

    volatile bool AllThreadsCompleted; // Глобальная переменная
    ....
    while (!AllThreadsCompleted);

Соответствующий ассемблерный код в Release-версии:

    $LL2@main:

    ; 9    :
    ; 10   :   while (!AllThreadsCompleted);

        movzx eax, BYTE PTR ?AllThreadsCompleted@@3_NC
         ; AllThreadsCompleted
        test al, al
        je SHORT $LL2@main

Однако иногда диагностика V712 выдаётся "совсем не там" и указывает на места, где вечного цикла вообще быть не должно. В таком случае, скорее всего, пустой цикл появился случайно из-за опечатки. В подобной ситуации диагностика часто (но не всегда) пересекается с диагностикой V715.

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки при работе с многопоточными примитивами (интерфейсами запуска потоков на выполнение, синхронизации и обмена данными между потоками и пр.).

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

CWE-835 CERT-MSC06-C

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