14

在 C 和 C++ 中,变量可以标记为volatile,这意味着编译器不会优化它,因为它可能在声明对象之外被修改。Delphi编程中是否有等价物?如果不是关键字,也许可以解决?

我的想法是使用Absolute,但我不确定,这可能会带来其他副作用。

4

5 回答 5

15

简短的回答:没有。

但是,如果您遵循这种方法,我不知道编译器的保守方法会改变读取或写入次数的任何情况:

读取跨线程可见位置时,在进行任何进一步操作之前将其值保存到本地;同样,将写入限制为单个分配。

当表达式之间存在对非内联方法的调用时,Delphi 编译器不会对非本地位置表达式执行公共子表达式消除 (CSE),因为编译器不进行过程间优化,因此即使对于单个位置表达式也不正确-线程代码。

因此,您可能希望使用 InterlockedExchange() 进行读写以强制执行此操作;此外,这将导致内存完全屏障,因此处理器也不会重新排序读取和写入。

于 2008-10-24T01:27:41.123 回答
11

根据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 编译器都支持以下属性:

于 2016-05-10T17:37:38.837 回答
1

我不知道任何等价物,我也不认为绝对指令会对您有所帮助。absolute允许您拥有两个使用相同地址的变量,但我认为它不会阻止编译器优化对该内存的引用。

我想您可以使用指针并自己管理它。这样,无论编译器如何优化指针值的检索,它都不应该假设存储在地址中的值与上次读取它时相同,但这纯粹是推测。

于 2008-10-24T01:03:00.643 回答
1

Delphi for .Net 也没有关键字,但 .Net 平台有它的 util 函数。请参阅Thread.VolatileReadThread.VolatileWrite

于 2008-10-24T08:01:55.180 回答
0

使用动态分配的指针?

var
  MyVarPtr: ^integer;
begin
  New(MyVarPtr);
  MyVarPtr^ := 5;
...

这应该可以防止编译器将寄存器用于整数值(但它可能仍使用寄存器作为地址)。不过,我不确定这与 volatile 相比如何。

于 2008-10-24T06:50:02.283 回答