2016-02-23 6 views
9

coupleshowstoppersの後、.NET 4.6ランタイムへの移行が遅れました。VBのイテレーター関数で重大な問題が発生するまで、最終的にC#6/VB14コンパイラーに移行するのが快適でした。 NETはローカル変数を投げ捨てる。VB.NETイテレーター機能がローカル変数を失う

次のコード例は、Visual Studio 2015/msbuildでリリースモード(最適化)でコンパイルされたときに、コメント行にnull参照例外をスローします。

Module Module1 

    Sub Main() 
     For Each o As Integer In GetAllStuff() 
      Console.WriteLine(o.ToString()) 
     Next 

     Console.ReadKey() 

    End Sub 

    Private Iterator Function GetAllStuff() As IEnumerable(Of Integer) 
     Dim map As Dictionary(Of String, String) = New Dictionary(Of String, String) 
     Dim tasks As New List(Of Integer) 
     tasks.Add(1) 

     For Each task As Integer In tasks 
      Yield task 
     Next 

     'The value of map becomes null here under the new VB14 compiler in Release on .NET 4.6' 
     For Each s As String In map.Values 
      Yield 100 
     Next 
    End Function 

End Module 

これはかなり恐ろしいことです。

特に、このコードのC#に相当するものは問題なく実行されます。さらに重要なことは、これはVBコンパイラの以前のバージョンでも動作しており、動作していることです。 2つの異なるコンパイラによって作成されたステートマシン間のMSILを比較すると、新しいコンパイラはローカル変数保存用の.localsをほぼ排他的に使用しているように見えますが、古いコンパイラはローカル値を保存するためにステートマシン上で可変フィールドを使用していました。

何か不足していますか?私はVBでイテレータの改訂に関する文書を見つけることはできませんでしたが、それが当てはまるとは想像できませんでしたが、他の誰かがこの問題にぶつかったことはありませんでした。

この特定の例は、最初のforeachループの後にmapの構成を移動することで回避できますが、私の懸念は、この問題の真の味がないということです。私はコードを変更して「それを機能させる」ことに興味はありません。私たちの広範なコードベースで、私は同じ問題にぶつかるかもしれませんか?私はConnectに問題を提出しましたが、しばしばブラックホールのように感じます。

UPDATE

誰かがちょうどRoslynのGitHubのページで非同期ステートマシンと同じ問題を報告:https://github.com/dotnet/roslyn/issues/9001

うまくいけば、これは少し注意を取得するために開始します。

+0

.NET Framework 4.5.2に対してコンパイルされたVS2015でコードを実行しましたが、これも 'NullReferenceException'を生成します。したがって、.NET 4.6ランタイムには分離されていないように見えます。 –

+0

4.5.2または4.6に対してVS2013を使ってコンパイルすると、 'NullReferenceException'が出ません。だから、あなたが言うように、これはフレームワークの問題ではなく、コンパイラの問題です。 –

+0

@Threadcreator:あなたのコードは、私にとって完璧に機能します。 Windows 10 Pro(x64)、Windowsデスクトップ用Visual Studio 2015 Expressを使用します。 Targetframework:4.5 – SiriSch

答えて

1

まず、私がRoslynチームで提起した問題に注意を払ってくれてありがとう。

私はhttps://github.com/dotnet/roslyn(マスターブランチ)から最新のロザリンソースを引っ張って、このようになりますBasicCompilerEmitTestプロジェクトに余分なユニットテストを追加しました:これが原因に複雑な混乱のように見えるかもしれ

Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests 

Public Class KirillsTests 
    Inherits BasicTestBase 

    <Fact> 
    Public Sub IteratorVariableCaptureTest() 
    Dim source = 
<compilation name="Iterators"> 
    <file name="a.vb"> 
Imports System 
Imports System.Collections.Generic 

Module Module1 

    Sub Main() 
     For Each o As Integer In GetAllStuff() 
      Console.WriteLine(o.ToString()) 
     Next 

     Console.WriteLine("done") 
    End Sub 

    Private Iterator Function GetAllStuff() As IEnumerable(Of Integer) 
     Dim map As Dictionary(Of String, String) = New Dictionary(Of String, String) 
     Dim tasks As New List(Of Integer) 
     tasks.Add(1) 

     For Each task As Integer In tasks 
      Yield task 
     Next 

     'The value of map becomes null here under the new VB14 compiler in Release on .NET 4.6' 
     For Each s As String In map.Values 
      Yield 100 
     Next 
    End Function 

End Module 
    </file> 
</compilation> 

    Dim expectedOutput = <![CDATA[1 
done]]> 

    Dim compilation = CompilationUtils.CreateCompilationWithReferences(source, references:=LatestVbReferences, options:=TestOptions.DebugExe) 
    CompileAndVerify(compilation, expectedOutput:=expectedOutput) 
    CompileAndVerify(compilation.WithOptions(TestOptions.ReleaseExe), expectedOutput:=expectedOutput) 
    End Sub 

End Class 

XElementXCDataですが、これは他のRoslyn単体テストで使用されているフォーマットです。 (CompileAndVerifyは、単に例外を無視するように)私は正常に完了したことを追跡することができるように​​とConsole.ReadKey()を交換している -

私はあなたがあなたの質問に投稿されたコードに1つの改変を行いました。

上記のテストに合格します。そこにはNullReferenceExceptionmap.Valuesのアクセスがなく、出力は次のようになります。

 
1 
done 

...予想通り。 Visual Studio 2015 Update 2に同梱されているかどうかはわかりませんが、あなたのバグは修正されているようです。

async variable capture issuepull request #7693で修正されましたが、DataFlowPass.SetSlotUnassigned以来書き直されました(2つのメソッドに分割され、変更された)ので、私はあなたが発見されたイテレータの問題は、その具体的なプル要求によって、または他のいくつかのコードの変更により修正されたかどうかを確認することができません。

+2

これは本当にアップデート2のCTPで対処されています。特定の修正プログラムの詳細を知るために、マイクロソフトのサポートを受けている電話機を爆破し、私が提供している情報で何かを更新する予定です。残念ながら、2015/4.6は長いCTPのように感じています。プラットフォームの安定性は、.NETのような大きなセールスポイントでした... – roken

+1

@roken、修正がすぐに出荷されていることを知っておいてよかったです。 Roslynはまだ初期の段階にあり、あなたが正しいと思っています。実験的な感じが少しあります。それは多くの点でエキサイティングな時間ですが、この質問がデモストレーションを行う理由は必ずしも良いとは限りません。 –

関連する問題