2017-06-02 25 views
3

予期せぬ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. 

"明らか"、この第3のプログラムは同じ値を出力最初の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です。これはcompiのようですlerはfcnへの呼び出しで2番目の匿名関数をwritelnに使用します。

これはDelphi 2009コンパイラのバグのようですが、Delphiの匿名関数についてのより微妙な詳細を理解できないこともあります。どう思いますか?

+1

FWIW、10.2東京では「1」が表示されます。 XEでも。だからこれはおそらくDelphi 2009での匿名関数の処理方法のバグでしょう。 –

+0

私は2番目の匿名関数が何らかの形で最初のものに置き換わると仮定します。私は、しかし、どのように知りません。しかし、私にとっては、Delphi 2009のバグのように見えます。 –

+1

@RudyVelthuis、ちょうどQuality Centralを検索して、それがなくなったことを知りました!何が起こっている?そして私は、不規則なフレームが間違ってここで再利用され、最初のフレームが置き換えられることに同意します。 –

答えて

1

これは間違いなくバグであると思われますが、質問で受け取ったコメントによれば、これは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以降でリクエストのインライン化を行います。もちろん、インライン展開がまったく重要ではないと思われる場合は、単にリクエストを完全に削除することができます。