Оптимизатор, удаляющий строки разыменования указателя

У меня проблема, когда оптимизатор, кажется, удаляет строки кода, которые совершенно необходимы. Немного предыстории: у меня есть программа, которая взаимодействует с драйвером PCIe. У меня есть целочисленный указатель UINT32 *bar_reg;, который указывает на адрес пользовательского пространства регистра BAR, с которым я общаюсь. Чтобы записать в регистр, я просто разыменовываю указатель. *(bar_reg + OFFSET) = value;

Без оптимизаций работает нормально. Однако, как только я включаю любой уровень оптимизации, все строки, которые ссылаются на указатель, удаляются. В конце концов я обнаружил это, пройдя через Visual Studio. Однако это происходит независимо от платформы. До сих пор мне удавалось обходиться отключенным оптимизатором, но кто-то, использующий код моей библиотеки в Linux, хочет включить оптимизацию прямо сейчас. Поэтому мне любопытно, почему возникает эта проблема и какое наиболее разумное решение/обходной путь.


person Alex Crook    schedule 21.11.2014    source источник
comment
Оптимизированный код ведет себя иначе, как правило, из-за неопределенного поведения.   -  person Neil Kirk    schedule 23.11.2014


Ответы (2)


Используйте ключевое слово volatile, чтобы предотвратить оптимизацию этой переменной.

Например:

volatile UINT32 *bar_reg;

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

person bialpio    schedule 21.11.2014

Проблема, с которой вы столкнулись, связана с правилом "как если", которое позволяет оптимизатору преобразовать ваш код любым способом, пока это не влияет на наблюдаемое поведение программы.

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

В вашем случае данные наблюдают за пределами вашей программы, и способ указать это компилятору и оптимизатору через volatile, cppreference сообщает нам (выделение мое идет вперед):

объект с типом volatile-qualified, или подобъект volatile-объекта, или изменяемый подобъект const-volatile-объекта. Каждый доступ (операция чтения или записи, вызов функции-члена и т. д.) к изменчивому объекту рассматривается как видимый побочный эффект в целях оптимизации [...]

Для справки, правило «как если бы» описано в проекте стандарта C++ в разделе 1.9, в котором говорится:

[...] Скорее, соответствующие реализации требуются для эмуляции (только) наблюдаемого поведения абстрактной машины, как объяснено ниже.

а в отношении правила как если бы volatile также рассматривается в разделе 1.9 и гласит:

Доступ к volatile-объектам оценивается строго по правилам абстрактной машины.

person Shafik Yaghmour    schedule 23.11.2014