[c++] Почему существует летучесть?



6 Answers

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

Question

Что делает ключевое слово volatile ? В C ++ какая проблема решена?

В моем случае я никогда в этом не нуждался.




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

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

Рассмотрим следующие случаи

1) Глобальные переменные, измененные процедурой обслуживания прерываний вне области видимости.

2) Глобальные переменные в многопоточном приложении.

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

1) Если оптимизация включена, код может работать не так, как ожидалось.

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

Неустойчивый: лучший друг программиста

https://en.wikipedia.org/wiki/Volatile_(computer_programming)




Одно из них, о котором я должен напомнить, - в функции обработчика сигнала, если вы хотите получить доступ / изменить глобальную переменную (например, пометить ее как exit = true), вы должны объявить эту переменную как «volatile».




Из статьи встраиваемых систем Дэн Сакс:

«Волатильный объект - это объект, значение которого может изменяться спонтанно. То есть, когда вы объявляете объект изменчивым, вы сообщаете компилятору, что объект может измениться, даже если никакие операторы в программе не изменят его».

Ссылки на 2 замечательные статьи г-на Сакса относительно ключевого слова volatile:

http://www.embedded.com/columns/programmingpointers/174300478 http://www.embedded.com/columns/programmingpointers/175801310




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




В стандарте C одним из мест для использования volatile является обработчик сигнала. Фактически, в стандарте C все, что вы можете безопасно сделать в обработчике сигнала, - изменить volatile sig_atomic_t переменную volatile sig_atomic_t или быстро выйти. Действительно, AFAIK, это единственное место в стандарте C, которое требует использования volatile чтобы избежать неопределенного поведения.

ISO / IEC 9899: 2011 §7.14.1.1. signal функция

¶5 Если сигнал встречается иначе, чем в результате вызова функции abort или raise , поведение не определено, если обработчик сигнала ссылается на любой объект со статикой или продолжительностью хранения потоков, который не является блокирующим атомом, кроме присвоения значение для объекта, объявленного как volatile sig_atomic_t , или обработчик сигнала вызывает любую функцию в стандартной библиотеке, _Exit функции abort функцию _Exit функцию quick_exit или функцию signal с первым аргументом, равным номеру сигнала, соответствующему сигнал, вызвавший вызов обработчика. Кроме того, если такой вызов функции signal приводит к возврату SIG_ERR, значение errno является неопределенным. 252)

252) Если какой-либо сигнал генерируется асинхронным обработчиком сигналов, поведение не определено.

Это означает, что в стандарте C вы можете написать:

static volatile sig_atomic_t sig_num = 0;

static void sig_handler(int signum)
{
    signal(signum, sig_handler);
    sig_num = signum;
}

и не намного больше.

POSIX гораздо более мягко относится к тому, что вы можете сделать в обработчике сигналов, но все еще существуют ограничения (и одно из ограничений заключается в том, что стандартная библиотека ввода-вывода - printf() и др. - нельзя использовать безопасно).




Большое приложение, с которым я работал в начале 1990-х годов, содержало обработку исключений на основе C с использованием setjmp и longjmp. Ключевое слово volatile было необходимо для переменных, значения которых необходимо сохранить в блоке кода, который служил в качестве предложения catch, чтобы эти вары не хранились в регистрах и не были уничтожены longjmp.




Related