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