Это в основном продолжение этот вопрос. Пока это выглядит так, если у меня есть такая функция:
void SecureZeroMemory( void* ptr, size_t cnt )
{
volatile char *vptr = (volatile char *)ptr;
while (cnt) {
*vptr = 0;
vptr++;
cnt--;
}
}
и назовите это так:
{
char buffer[size];
SecureZeroMemory( buffer, size );
}
тогда с buffer
не объявляется как volatile, не имеет значения, что используется указатель на volatile — сами данные не являются volatile, поэтому запись в переменную не составляет наблюдаемого поведения (1.9 / 6), и компилятору разрешено их оптимизировать.
Однако недавно я наткнулся на утверждение, что имеет значение только объявление указателя. В частности, C ++ 03 5.3.1 / 1 описывает косвенное обращение (*) следующим образом:
Унарный оператор * выполняет косвенное указание […] Если тип выражения — «указатель на T», тип результата — «T».
Таким образом, утверждение заключается в том, что из-за использования косвенного volatile char*
мы получаем volatile char
и записи в те, которые составляют наблюдаемое поведение, и больше не имеет значения, как объявляются фактические данные.
Действительно ли описание косвенного обращения в C ++ 03 5.3.1 / 1 гарантирует, что перезапись памяти с использованием volatile T*
указатель, как в приведенном выше примере, представляет собой наблюдаемое поведение и не может быть оптимизирован?
Я уверен, что все, что добавляет «новая» цитата, это *vptr
является выражением lvalue с типом volatile char
,
Тип lvalue не влияет на тип объекта, к которому относится это выражение lvalue, по той же причине, по которой указатель на const, указывающий на неконстантный объект, каким-то образом не делает объект const. Таким образом, первоначальный анализ не влияет на эту цитату — объект все еще не имеет волатильно-квалифицированного типа.
На обычном языке мы бы сказали, что тип *vptr
является volatile char &
, но 5/5 говорит: «Если выражение изначально имеет тип« ссылка на T », тип корректируется до T перед любым дальнейшим анализом». Вот почему *vptr
говорят, что имеет тип volatile char
не volatile char &
— перед анализом любого выражения вы удаляете ссылку из типа, даже если это lvalue.
Это интересный вопрос. Я думаю, что цель
стандартным было то, что это должно работать. При чтении стандарта
(C ++ 03, §1.9 / 6,7), однако:
Наблюдаемое поведение абстрактной машины — это ее последовательность
чтения и записи в изменчивые данные и вызовы ввода / вывода библиотеки
функции.Доступ к объекту, обозначенному изменчивым lvalue, изменяющим
объект, вызывающий библиотечную функцию ввода-вывода или вызывающий
функция, которая делает любую из этих операций со всех сторон
эффекты, которые являются изменениями в состоянии исполнения
среда. Оценка выражения может дать побочную
последствия. В определенных точках в последовательности выполнения
Точки последовательности, все побочные эффекты предыдущего
оценки должны быть полными и без побочных эффектов
последующие оценки должны быть проведены.
Казалось бы, разница в формулировках в двух пунктах
существенно: «наблюдаемое поведение» — это последовательность операций чтения
и пишет изменчивый данные. В твоем случае, buffer
является не
изменчивые данные, поэтому, по-видимому, компилятор может свободно оптимизировать
доступы прочь Я не думаю, что это намерение, но
кажется, это то, что говорится.
В вашем случае оптимизация была бы особенно простой,
поскольку преобразование в volatile происходит в самой функции.
Компилятор может легко определить, что vptr
не указывает на
данные, которые на самом деле изменчивы. Если вы измените параметр
введите в void volatile*
тогда компилятор должен будет увидеть
и сайт вызова, и функция одновременно, чтобы
смело делайте оптимизацию.
И, наконец, независимо от того, что говорит стандарт, компиляторы
имеют свои собственные интерпретации volatile
, На практике,
большинство, если не все компиляторы, предполагают, что вы используете
volatile
по причине, и будет генерировать машину
инструкции, чтобы сделать записи. (На практике это все, что
они будут делать, что означает, что порядок записи
видимый вне потока код, в котором находится поток
ход остается неопределенным. Это не проблема для вашего использования,
но это для многих других целей.)