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