Рассмотрим этот простой код:
void g();
void foo()
{
volatile bool x = false;
if (x)
g();
}
Вы можете видеть , что ни gcc
ни clang
оптимизируют из потенциального вызова g
. В моем понимании это правильно: абстрактная машина должна предполагать, что volatile
переменные могут измениться в любой момент (например, из-за аппаратного отображения), поэтому постоянное свертывание false
инициализации в if
проверку будет неправильным.
Но MSVC полностью исключает вызов g
(сохраняя чтение и запись в volatile
!). Это стандартное поведение?
Предыстория: я иногда использую этот вид конструкции, чтобы иметь возможность включать / выключать вывод отладочной информации на лету: компилятор должен всегда считывать значение из памяти, поэтому изменение этой переменной / памяти во время отладки должно соответствующим образом изменить поток управления , Выход MSVC перечитывает значение, но игнорирует его (предположительно, из-за постоянного свертывания и / или удаления мертвого кода), что, конечно, противоречит моим намерениям.
Редактирование:
Здесь
volatile
обсуждается исключение операций чтения и записи : разрешено ли компилятору оптимизировать локальную переменную переменной? (спасибо, Натан!) Я думаю, что стандарт совершенно ясно, что эти чтения и записи должны произойти. Но это обсуждение не охватывает вопрос о том, является ли законным компилятор принимать результаты этих чтений как должное и оптимизировать их на этом основании. Я предполагаю, что это не указано / не указано в стандарте, но я был бы счастлив, если бы кто-то доказал, что я неправ.Конечно, я могу создать
x
нелокальную переменную, чтобы обойти проблему. Этот вопрос больше из любопытства.
источник
Ответы:
Я думаю, что [intro.execution] (номер параграфа может отличаться) можно использовать для объяснения поведения MSVC:
Стандарт не разрешает исключение чтения через изменчивое значение, но параграф выше может быть интерпретирован как позволяющий предсказать значение
false
.Кстати, Стандарт C (N1570 6.2.4 / 2) говорит, что
Неясно, может ли быть неявное хранилище в объекте с автоматической продолжительностью хранения в памяти C / объектной модели.
источник
volatile
покупает вас (кроме лишних операций чтения / записи), если оно игнорируется в целях оптимизации?TL; DR Компилятор может делать все, что захочет, для каждого изменяемого доступа. Но документация должна сказать вам: «Семантика доступа через volatile glvalue определяется реализацией».
Стандарт определяет для программы разрешенные последовательности «изменчивого доступа» и другого «наблюдаемого поведения» (достигаемого посредством «побочных эффектов»), которые реализация должна соблюдать в соответствии с «правилом« как будто ».
Но стандарт гласит (выделение жирным шрифтом):
Аналогично для интерактивных устройств (выделение жирным шрифтом):
(Во всяком случае, какой конкретный код генерируется для программы, стандартом не указано.)
Таким образом, хотя стандарт говорит, что изменчивый доступ не может быть исключен из абстрактных последовательностей побочных эффектов абстрактной машины и вытекающих из этого наблюдаемых поведений, которые определяет некоторый код (возможно), вы не можете ожидать, что что-либо будет отражено в объектном коде или реальном мире. поведение, если ваша документация компилятора не говорит вам, что представляет собой изменчивый доступ . То же самое для интерактивных устройств.
Если вас интересует изменчивость в отношении абстрактных последовательностей побочных эффектов абстрактной машины и / или последующих наблюдаемых поведений, которые определяет некоторый код (возможно), тогда скажите об этом . Но если вас интересует, какой соответствующий объектный код генерируется, вы должны интерпретировать это в контексте вашего компилятора и компиляции. .
Хронически люди ошибочно полагают , что для летучих доступов абстрактной оценки машина / чтение вызывает реализованное чтение & задание абстрактной машины / запись вызывает реализованную запись. Нет никаких оснований для этого убеждения, отсутствующей документации реализации, говорящей так. Когда / iff реализация говорит, что она действительно что-то делает при «изменчивом доступе», люди оправдывают ожидание чего-то - возможно, генерации определенного объектного кода.
источник
Я считаю, что законно пропускать чек.
Абзац, который все любят цитировать
не означает, что реализация должна предполагать, что такие хранилища возможны в любое время или для любой изменчивой переменной. Реализация знает, какие магазины возможны. Например, вполне разумно предположить, что такие неявные записи происходят только для изменчивых переменных, которые сопоставлены с регистрами устройства, и что такое сопоставление возможно только для переменных с внешней связью. Или реализация может предполагать, что такие записи происходят только в области памяти размером со слово, выровненных по словам.
Сказав это, я думаю, что поведение MSVC является ошибкой. Нет реальной причины оптимизировать вызов. Такая оптимизация может быть послушной, но она излишне злая.
источник
volatile
предполагается, что это является подсказкой реализации, что значение может быть изменено с помощью средств, неизвестных реализации.volatile
на этой платформе и вне этой спецификации, это всегда будет чушь.volatile
делает, и придерживаться этого. Я хочу сказать, что сам код (в соответствии со стандартной / абстрактной машиной C ++) не позволяет вам определить,g
может ли он быть вызван.