Пустой цикл в версии Release

161
20 февраля 2018, 06:54

Использую пустой цикл

while (botsReady < botsCount);

что бы просто не выполнять последующий код, пока все боты не будут готовы. На сборке Debug всё работает прекрасно, однако, когда я переключился на Release, то почему-то этот цикл.. сломался?

Он просто не работает, будто я написал вместо него system("pause");, но когда я пишу в тело цикла какой-нибудь код, типа

while (botsReady < botsCount) {
        cout << "q";
    }

то цикл внезапно начинает работать как и задумано, но если я напишу

while (botsReady < botsCount) {
    continue;
}

То снова ничего не работает.

Что это за приколы такие, и есть ли этому разумное объяснение? Использую MSVS17.

Answer 1

Согласно стандарту C++ любой цикл без видимых побочных эффектов обязан завершаться, в противном случае поведение неопределено. А неопределенное поведение (Undefined behavior, UB) - это такая штука, при которой разрешено происходить чему угодно - даже бесконечный цикл может выполниться за конечное время.

Ваш пустой цикл как раз и попадает под UB, из-за чего оптимизатор его просто выкидывает.

Для того, чтобы этого не происходило, надо переменную botsReady объявить как volatile - это одновременно даст видимые побочные эффекты циклу (чтение volatile-переменной - тоже побочный эффект), и запретит компилятору оптимизировать чтение этой переменной.

Но ваш код все равно неправильный, причем фатально неправильный. Нельзя создавать несколько потоков которые используют общие переменные без синхронизации. И еще нельзя ждать как это делаете вы - в активном ожидании. Вы понимаете, что пока вы в одном потоке греете процессор своим циклом - в другом потоке не может выполняться код вашего бота, потому что процессор занят?

Правильным решением будет использовать примитив синхронизации "барьер":

std::experimental::barrier ready_barrier = { botsCount + 1 };
// в потоке бота
ready_barrier.arrive_and_drop();
// в основном потоке
ready_barrier.arrive_and_wait(); 

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

READ ALSO
Почему CMake не находит GTest (Google Test)?

Почему CMake не находит GTest (Google Test)?

Существует готовый проектВ одном из cmake-файлов отрабатывает такая конструкция:

141
Запуск jar файла из консоли

Запуск jar файла из консоли

Программа должна скачивать файлы по HTTP протоколуВходные параметры: l – ссылка на файл

130
Выдает ошибку TiledMapTileMapObject cannot be cast toRectangleMapObject

Выдает ошибку TiledMapTileMapObject cannot be cast toRectangleMapObject

Что можно сделать,чтобы решить эту проблему? Exception in thread "LWJGL Application" javalang

170
com.android.tools.aapt2.Aapt2Exception Android Studio

com.android.tools.aapt2.Aapt2Exception Android Studio

После установки Андроид студио выводится такая ошибка:

271