Оптимизация — Гарантирует ли стандартное описание оператора косвенного обращения C ++ записи памяти не оптимизированы?

Это в основном продолжение этот вопрос. Пока это выглядит так, если у меня есть такая функция:

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* указатель, как в приведенном выше примере, представляет собой наблюдаемое поведение и не может быть оптимизирован?

13

Решение

Я уверен, что все, что добавляет «новая» цитата, это *vptr является выражением lvalue с типом volatile char,

Тип lvalue не влияет на тип объекта, к которому относится это выражение lvalue, по той же причине, по которой указатель на const, указывающий на неконстантный объект, каким-то образом не делает объект const. Таким образом, первоначальный анализ не влияет на эту цитату — объект все еще не имеет волатильно-квалифицированного типа.

На обычном языке мы бы сказали, что тип *vptr является volatile char &, но 5/5 говорит: «Если выражение изначально имеет тип« ссылка на T », тип корректируется до T перед любым дальнейшим анализом». Вот почему *vptr говорят, что имеет тип volatile charне volatile char & — перед анализом любого выражения вы удаляете ссылку из типа, даже если это lvalue.

[Правка: в моем ответе раньше был текст о том, что cv-квалификации незначительны для необъектных значений целочисленного типа. Это было верно (преобразования lvalue в rvalue не-классовых типов отбрасывают cv-qualifiers, 4.1 / 1), но не имеют значения (я ошибочно подумал, что, поскольку в цитируемом вами тексте упоминается не ссылочный тип, речь идет о типе после этого преобразование)]
4

Другие решения

Это интересный вопрос. Я думаю, что цель
стандартным было то, что это должно работать. При чтении стандарта
(C ++ 03, §1.9 / 6,7), однако:

Наблюдаемое поведение абстрактной машины — это ее последовательность
чтения и записи в изменчивые данные и вызовы ввода / вывода библиотеки
функции.

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

Казалось бы, разница в формулировках в двух пунктах
существенно: «наблюдаемое поведение» — это последовательность операций чтения
и пишет изменчивый данные. В твоем случае, buffer является не
изменчивые данные, поэтому, по-видимому, компилятор может свободно оптимизировать
доступы прочь Я не думаю, что это намерение, но
кажется, это то, что говорится.

В вашем случае оптимизация была бы особенно простой,
поскольку преобразование в volatile происходит в самой функции.
Компилятор может легко определить, что vptr не указывает на
данные, которые на самом деле изменчивы. Если вы измените параметр
введите в void volatile*тогда компилятор должен будет увидеть
и сайт вызова, и функция одновременно, чтобы
смело делайте оптимизацию.

И, наконец, независимо от того, что говорит стандарт, компиляторы
имеют свои собственные интерпретации volatile, На практике,
большинство, если не все компиляторы, предполагают, что вы используете
volatile по причине, и будет генерировать машину
инструкции, чтобы сделать записи. (На практике это все, что
они будут делать, что означает, что порядок записи
видимый вне потока код, в котором находится поток
ход остается неопределенным. Это не проблема для вашего использования,
но это для многих других целей.)

4

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector