【问题标题】:Delphi anonymous function passed to inlined functionDelphi 匿名函数传递给内联函数
【发布时间】:2017-06-02 20:01:47
【问题描述】:

我偶然发现了 Delphi 2009 的意外行为。在调查了我的代码中的一个奇怪错误之后,我设法缩小了问题的范围并创建了一个我在下面展示的最小示例。

当然,下面的代码打印值1:

program Example1;

{$APPTYPE CONSOLE}

type
  TIntFcn = reference to function(const X: integer): integer;

function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
  result := AFunction(a);
end;

begin

  writeln(fcn(function(const X: integer): integer
    begin
      result := 1;
    end, 0));

end.

同样,这个程序打印值 2:

program Example2;

{$APPTYPE CONSOLE}

type
  TIntFcn = reference to function(const X: integer): integer;

function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
  result := AFunction(a);
end;

begin

  writeln(fcn(function(const X: integer): integer
    begin
      result := 2;
    end, 0));

end.

“显然”,这第三个程序打印的值与第一个相同,即 1:

program Produce;

{$APPTYPE CONSOLE}

type
  TIntFcn = reference to function(const X: integer): integer;

function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
  result := AFunction(a);
end;

begin

  writeln(fcn(function(const X: integer): integer
    begin
      result := 1;
    end, 0));

  fcn(function(const X: integer): integer
    begin
      result := 2;
    end, 0); // discard the output

end.

但是,输出不是 1,而是 2。似乎编译器在调用 writeln 中的 fcn 时使用了第二个匿名函数。

在我看来,这似乎是 Delphi 2009 编译器中的一个错误,但也可能只是我不了解 Delphi 中有关匿名函数的更微妙的细节。你怎么看?

【问题讨论】:

  • FWIW,在 10.2 Tokyo,显示 1。在 XE 中也是如此。所以这可能是 Delphi 2009 处理匿名函数的一个错误。
  • @RudyVelthuis,刚要在 Quality Central 中搜索,发现它不见了!?怎么了?而且我同意匿名框架在这里被错误地重用,导致第一个被替换。
  • @LURD 你的意思是 QC 没了?这也让我感到惊讶,虽然不是太多。它已经被弃用了一段时间,QP(质量门户)取代了它。
  • 看起来 QC 可能终于死了。 qc.embarcadero.com 现在重定向到 quality.embarcadero.com
  • 这是一种将错误抛在脑后的方法。很方便...

标签: delphi inline anonymous-function delphi-2009


【解决方案1】:

这显然是一个错误,根据收到的有关问题的 cmets,这已在 Delphi XE 中修复。如果编译器无法正确处理,可能最简单的解决方法是跳过要求内联:

program Solve;

{$APPTYPE CONSOLE}

type
  TIntFcn = reference to function(const X: integer): integer;

function fcn(AFunction: TIntFcn; a: integer): integer;
  {$IF CompilerVersion >= 22}inline;{$IFEND} {Warning: Horrible bug in Delphi 2009}
begin
  result := AFunction(a);
end;

begin

  writeln(fcn(function(const X: integer): integer
    begin
      result := 1;
    end, 0));

  fcn(function(const X: integer): integer
    begin
      result := 2;
    end, 0); // discard the output

end.

在大多数情况下,性能损失在 Delphi 2009 中应该可以忽略不计,并且您确实在 XE 及更高版本中请求内联。当然,如果您认为内联根本不重要,您可以完全删除请求。

【讨论】:

    猜你喜欢
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    • 2015-01-07
    • 1970-01-01
    相关资源
    最近更新 更多