在 C 和 C++ 中,变量可以标记为volatile,这意味着编译器不会优化它,因为它可能在声明对象之外被修改。Delphi编程中是否有等价物?如果不是关键字,也许可以解决?
我的想法是使用Absolute,但我不确定,这可能会带来其他副作用。
在 C 和 C++ 中,变量可以标记为volatile,这意味着编译器不会优化它,因为它可能在声明对象之外被修改。Delphi编程中是否有等价物?如果不是关键字,也许可以解决?
我的想法是使用Absolute,但我不确定,这可能会带来其他副作用。
简短的回答:没有。
但是,如果您遵循这种方法,我不知道编译器的保守方法会改变读取或写入次数的任何情况:
读取跨线程可见位置时,在进行任何进一步操作之前将其值保存到本地;同样,将写入限制为单个分配。
当表达式之间存在对非内联方法的调用时,Delphi 编译器不会对非本地位置表达式执行公共子表达式消除 (CSE),因为编译器不进行过程间优化,因此即使对于单个位置表达式也不正确-线程代码。
因此,您可能希望使用 InterlockedExchange() 进行读写以强制执行此操作;此外,这将导致内存完全屏障,因此处理器也不会重新排序读取和写入。
根据The Delphi Language for Mobile Development白皮书,Delphi 的移动编译器[volatile]
自首次推出以来就支持一个属性:
该
volatile
属性用于标记受不同线程更改的字段,以便代码生成不会优化将值复制到寄存器或另一个临时内存位置。您可以使用该
volatile
属性来标记以下声明:
- 变量(全局和局部)
- 参数
- 记录或类的字段。
您不能使用 volatile 属性来标记以下声明:
- 类型
- 过程、函数或方法
- 表达式
type TMyClass = class private [volatile] FMyVariable: TMyType; end;
从 Delphi 10.1 Berlin 开始,桌面编译器现在也支持[volatile]
。
现在,所有 Delphi 编译器都支持以下属性:
我不知道任何等价物,我也不认为绝对指令会对您有所帮助。absolute允许您拥有两个使用相同地址的变量,但我认为它不会阻止编译器优化对该内存的引用。
我想您可以使用指针并自己管理它。这样,无论编译器如何优化指针值的检索,它都不应该假设存储在地址中的值与上次读取它时相同,但这纯粹是推测。
Delphi for .Net 也没有关键字,但 .Net 平台有它的 util 函数。请参阅Thread.VolatileRead和Thread.VolatileWrite。
使用动态分配的指针?
var
MyVarPtr: ^integer;
begin
New(MyVarPtr);
MyVarPtr^ := 5;
...
这应该可以防止编译器将寄存器用于整数值(但它可能仍使用寄存器作为地址)。不过,我不确定这与 volatile 相比如何。