在 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;
...

这应该使编译器不使用寄存器来获取整数值(但它可能仍然使用一个作为地址)。不过,我不确定这与挥发性有何不同。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top