Многие платформы могут по существу с нулевой стоимостью предлагать полезные поведенческие гарантии, более сильные, чем стандартные мандаты, но, к сожалению, в стандарте нет средств, с помощью которых программа может определить, какие гарантии доступны, и оптимизаторы могут переставлять код без учета того, будет ли это нарушено. программы, использующие гарантии, в противном случае обеспечивали бы платформу практически без затрат.
Например, учитывая int x, y, *p;
, рассмотрите следующий фрагмент кода:
x = 0x0123;
y = *p;
... maybe some computations here that use up CPU registers
x = 0x0124;
Реализация может заметить, что между хранилищами 0x0123
и 0x0124
значение x
читается, но не записывается, и, таким образом, можно изменить последнюю запись с последовательности, подобной mov ax,0124h / mov _x,ax
или mov word [_x],0124h
(на 8088, любая последовательность будет составлять шесть байтов плюс две операции с памятью) на inc byte _x
(четыре байта плюс две операции с памятью). Однако такой код может плохо работать, если существует промежуточная запись какого-либо другого значения, например 0x00FF. Нисходящий код может рассматривать любое ненулевое значение x
как одинаково приемлемое, и исходный код никогда не запрашивал записи какого-либо значения, чей нижний байт равен нулю, но если внешняя запись хранит 0x00FF непосредственно перед инструкцией inc byte _x
, x
можно оставить равным нулю, что довольно неожиданно.
Во многих случаях стоимость воздержания от такой оптимизации будет меньше, чем стоимость включения барьеров памяти, достаточных для предотвращения скачек данных, но, к сожалению, нет хороший способ указать такую семантику, если не заменить x
на «atomi c int», что может потребовать дополнительной памяти, и изменить все обращения к x
, чтобы явно использовать расслабленную семантику.