簡體   English   中英

調試器步進if語句和lambda表達式

[英]Debugger stepping in if statement and lambda expression

使用以下代碼作為示例:

if (true)
{
    string foo = null;
    List<string> bar = new List<string>
    {
        "test"
    };
    bar.Any(t => t == foo);
}

如果我以常規方式運行此程序(沒有斷點或任何其他中斷),一切都可以正常運行,無異常或錯誤(正如您所期望的那樣)。

現在,如果我在if語句上放置一個斷點並將光標移動到大括號,如下圖所示(使用我的鼠標,不使用F10,所以跳過if(true)語句):

在此輸入圖像描述

當調試器執行語句string foo = null時,我得到類型System.NullReferenceException的異常

它似乎與變量fooif語句中的lambda表達式中使用的事實有關。 我已經在Visual Studio 2012和2013(專業版和終極版)上測試並重現了這一點。

為什么會發生這種情況的任何想法?

推測你正在跳過閉包生成的評論是正確的。 移動指令指針時,不保證C#程序具有任何特定行為。 如果你這樣做會傷害,不要這樣做。

實際上這是一個小謊言。 有保證。 例如,您可以保證在可驗證的程序中這樣做不會破壞clr的內部數據結構。 您可以保證這樣做不會使堆棧錯位。 等等。 但是,您的數據結構不能表達或暗示任何保證! 您將指令指針移動到您的危險之中。

Eric的回答和評論已經描述了為什么它會發生。 我想強調在這個特殊情況下發生的事情。

這是生成的IL:

.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack 3
    .locals init (
        [0] class [mscorlib]System.Collections.Generic.List`1<string> bar,
        [1] class [mscorlib]System.Collections.Generic.List`1<string> <>g__initLocal0,
        [2] class StackOverflow.Program/<>c__DisplayClass2 CS$<>8__locals3,
        [3] bool CS$4$0000)
    L_0000: nop 
    L_0001: ldc.i4.0 
    L_0002: stloc.3 
    L_0003: newobj instance void StackOverflow.Program/<>c__DisplayClass2::.ctor()
    L_0008: stloc.2 
    L_0009: nop 
    L_000a: ldloc.2 
    L_000b: ldnull 
    L_000c: stfld string StackOverflow.Program/<>c__DisplayClass2::foo
    L_0011: newobj instance void [mscorlib]System.Collections.Generic.List`1<string>::.ctor()
    L_0016: stloc.1 
    L_0017: ldloc.1 
    L_0018: ldstr "test"
    L_001d: callvirt instance void [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
    L_0022: nop 
    L_0023: ldloc.1 
    L_0024: stloc.0 
    L_0025: ldloc.0 
    L_0026: ldloc.2 
    L_0027: ldftn instance bool StackOverflow.Program/<>c__DisplayClass2::<Main>b__1(string)
    L_002d: newobj instance void [mscorlib]System.Func`2<string, bool>::.ctor(object, native int)
    L_0032: call bool [System.Core]System.Linq.Enumerable::Any<string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, bool>)
    L_0037: pop 
    L_0038: nop 
    L_0039: ret 
}

注意L_0003行。 它調用ctor為自動生成的c__DisplayClass2類,它保存foo字段,因為你在lambda中使用它。 所以NullReferenceException發生是因為你的跳過類初始化,但是你在一行L_000c上分配實例的字段foo

太糟糕了,沒有簡單的方法來調試IL級別來驗證這一點,但我們可以調試JITed程序(Debug - > Disassembly)

這是你的第一個斷點:

在此輸入圖像描述

然后光標移動后:

在此輸入圖像描述

其中一個滑雪呼叫教練必須從L_0003打電話給ctor。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM