Полезен ли volatile вообще в однопоточном приложении на языке C++?


Как говорится в названии-есть ли какой-либо случай, в котором volatile полезно в контексте однопоточного программирования? Я знаю, что он используется, чтобы убедиться, что значение переменной всегда проверяется в памяти, так что есть ли случай, в котором это значение может измениться (в приложении ST) таким образом, что приложение/компилятор не заметит?

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

Edit: как мне было указано, вопрос не является агностическим по отношению к языку. Я делаю его специфичным для C++ (я читал, что есть различия и в версиях C++, но я надеюсь, что они недостаточно велики, чтобы сделать этот вопрос слишком широким).

3 4

3 ответа:

Это ответ для C и C++

Да! Когда переменная сопоставляется с аппаратным регистром (например, устройством ввода-вывода). Аппаратное обеспечение изменяет регистр независимо от приложения.

Пример:

extern volatile uint32_t MY_DEVICE_START; // write-only register
extern volatile const uint32_t MY_DEVICE_STATUS; // read-only register
extern volatile uint32_t MY_DEVICE_DATA; // read-write register

...
MY_DEVICE_DATA = 42; // send input to the device
MY_DEVICE_START = 1; // start the device
while (MY_DEVICE_STATUS == 0) {} // busy-wait for the device to finish
int result = MY_DEVICE_DATA; // read output from the device
...

По крайней мере, в C / C++ это главная причина. Volatile даже не рекомендуется для многопоточного использования .

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

Один из примеров, когда volatile может быть полезен в программе на языке Си или Си++, - это отладка. Рассмотрим следующий пример:
void do_thing(const std::vector<int>& v) {
    if (v.empty()) {
        do_thing_1();
    } else {
        do_thing_2();
    }
}

Если я хочу протестировать вышеупомянутую функцию и заставить ее принять ветвь true или false во время отладки, я могу вставить переменную volatile в if условие:

void do_thing(const std::vector<int>& v) {
    volatile bool condition = v.empty();
    if (condition) {
        do_thing_1();
    } else {
        do_thing_2();
    }
}

Я делаю это volatile, чтобы оптимизатор не полностью оптимизировал переменную. Это упрощает установку точки останова на if , а затем я могу изменить condition (без необходимости изменять v).

Я также могу сделать переменную condition переменной static, чтобы мне не нужно было постоянно нажимать на точку останова: я могу нажать ее один раз, установить ее, и тогда она "запомнит" мой выбор.

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

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

Ответ является более или менее общим и может быть неверным в зависимости от языка, как уже упоминалось выше.