2
當我試圖瞭解回合實際上做我最後看一個簡單的控制檯程序(從C#.NET 4.5編譯器發出)的IL:爲什麼編譯器發出一個stloc後跟一個ldloca?
.maxstack 2
.locals init (float64 V_0,
float64 V_1)
IL_0000: ldc.r8 2.00
IL_0009: stloc.0
IL_000a: ldloca.s V_0
IL_000c: call instance string [mscorlib]System.Double::ToString()
IL_0011: call void [mscorlib]System.Console::WriteLine(string)
IL_0016: ldloc.0
IL_0017: ldc.i4.5
IL_0018: call float64 [mscorlib]System.Math::Round(float64,
int32)
IL_001d: stloc.1
IL_001e: ldloca.s V_1
IL_0020: call instance string [mscorlib]System.Double::ToString()
IL_0025: call void [mscorlib]System.Console::WriteLine(string)
IL_002a: ret
而且我注意到IL_001d的指示, IL_001e。它們對我來說似乎是多餘的,將值存儲在本地並在此之後加載相同的值。刪除它們並重新組裝IL給我一個NullReferenceException,所以我猜測它有一些指向。但我無法弄清楚。
那麼NullReferenceException從哪裏來?爲什麼編譯器會發出這兩條指令? 除了上面給出的IL之外,沒有更多的IL,當然除了一些元。
謝謝你的回答。根據你的指針進行更多的研究之後,我現在完全可以瞭解它。 '調用'操作碼需要將參考推送到堆棧上,並且在堆棧上推入一個雙精度值不能滿足該要求。所以它需要存儲在一個變量中,並且該變量的引用被壓入堆棧,所以'call'很快樂。而且我認爲發生了NullReferenceException,因爲double值表示的地址沒有任何內容。 – Vincent 2014-11-02 17:32:13
我認爲在這種情況下,異常類型取決於堆棧頂部的當前值:它可能是NullReferenceException中的任何內容,將垃圾打印到訪問衝突。 – 2014-11-03 08:24:11
關於'System.Double :: ToString'調用,這是實例方法,它期望堆棧中'Double'結構的地址。由於'double'變量具有與'Double'結構相同的內存佈局,這使得'ToString'方法很開心。順便說一句,這段代碼表明,爲'int,double'和類似類型調用'ToString'不會導致裝箱。 – 2014-11-03 08:27:17