2013-09-29 37 views
2

更新一些我的代碼示例進行培訓我已經注意到一些以前未被CLR未初始化的本地內存現在是歸零爲什麼在.Net 4.5中更改內存初始化規則?

這裏是一個小CIL示例,演示了 「問題」:

.assembly Test{} 

.assembly extern mscorlib{} 

.class S extends [mscorlib]System.ValueType 
{ 
    .field public int32 n; 
} 

.method static void F() 
{ 
    .locals (int32, valuetype S) 

    ldloc 0 
    call void [mscorlib]System.Console::WriteLine(int32) 

    ldloca 1 
    ldfld int32 S::n 
    call void [mscorlib]System.Console::WriteLine(int32) 

    ret 
} 

.method static void Main() 
{ 
    .entrypoint 

    .locals (int32, valuetype S) 

    ldloc 0 
    call void [mscorlib]System.Console::WriteLine(int32) 

    ldloca 1 
    ldfld int32 S::n 
    call void [mscorlib]System.Console::WriteLine(int32) 

    call void F() 

    ret 
} 

這裏是輸出:

  • NET 2.0(我幾乎可以肯定它與.Net 4.0相同):

    $ /Windows/Microsoft.NET/Framework/v2.0.50727/ilasm.exe Test.il 
    
    Microsoft (R) .NET Framework IL Assembler. Version 2.0.50727.5420 
    Copyright (c) Microsoft Corporation. All rights reserved. 
    Assembling 'Test.il' to EXE --> 'Test.exe' 
    Source file is ANSI 
    
    Assembled global method F 
    Assembled global method Main 
    Creating PE file 
    
    Emitting classes: 
    Class 1:  S 
    
    Emitting fields and methods: 
    Global Methods: 2; 
    Class 1 Fields: 1; 
    Resolving local member refs: 3 -> 3 defs, 0 refs, 0 unresolved 
    
    Emitting events and properties: 
    Global 
    Class 1 
    Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved 
    Writing PE file 
    Operation completed successfully 
    Test.il(6) : warning -- Non-sealed value class, made sealed 
    
    $ ./Test.exe 
    211384 
    0 
    2157704 
    2157328 
    
  • .net 4.5:

    $ /Windows/Microsoft.NET/Framework/v4.0.30319/ilasm.exe Test.il 
    
    Microsoft (R) .NET Framework IL Assembler. Version 4.0.30319.17929 
    Copyright (c) Microsoft Corporation. All rights reserved. 
    Assembling 'Test.il' to EXE --> 'Test.exe' 
    Source file is ANSI 
    
    Assembled global method F 
    Assembled global method Main 
    Creating PE file 
    
    Emitting classes: 
    Class 1:  S 
    
    Emitting fields and methods: 
    Global Methods: 2; 
    Class 1 Fields: 1; 
    Resolving local member refs: 3 -> 3 defs, 0 refs, 0 unresolved 
    
    Emitting events and properties: 
    Global 
    Class 1 
    Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved 
    Writing PE file 
    Operation completed successfully 
    Test.il(6) : warning : Non-sealed value class, made sealed 
    
    $ ./Test.exe 
    0 
    0 
    0 
    0 
    

我很好奇這背後實施變革的理由。

因此,歡迎任何反饋意見,尤其是來自內部人員,或對任何文章或更好的參考文獻的參考。 :)

在此先感謝。

+1

這幾乎可以肯定地在CIL運行時規範中。你看過那裏嗎?將字段歸零而不是未初始化字段幾乎肯定比獲取隨機結果更可取。那裏不需要太多理由。 –

+0

在ECMA-335標準中,我看到「如果指定了init,變量將根據它們的類型初始化爲其默認值:參考 類型被初始化爲空,並且值類型被清零。但是這裏沒有「init」。 – Pragmateek

+3

我懷疑Microsoft最初是否將變量初始化爲語言編譯器的決定。但是由於像你這樣的人正在更頻繁地挖掘真正的IL,並且IL程序和C#程序一樣有效,所以將初始化重新推回到IL中是有意義的。 –

回答

2

這只是一個巧合,沒有任何東西會故意清除你的本地人。抖動試圖將你的本地人保存在寄存器中,如果沒有必要,它甚至不會分配堆棧空間。你的程序很小,當你不用/ 32bit優先標記進行編譯時,選擇本地寄存器的可能性很大,這個寄存器在當前線程中沒有被使用過,並且仍然沒有值。當你:

  • 用/ 32bit優先標記編譯代碼。 32位代碼具有較少的寄存器,因此您的本地可能存儲在髒堆棧或髒寄存器中。
  • 爲您的值類型創建更多的字段,或者使用更多的本地語言,因此它們不適合寄存器集,或者抖動不選擇將它們存儲在那裏。
  • 做更多的事情在你的方法是什麼涉及寄存器

我不知道爲什麼你需要做出更多的努力相比以前的版本4.5版找到未初始化值。也許這是抖動的一些變化的副作用,但我只是猜測。重點是你仍然需要在你的本地人的初始化標誌,以確保他們得到零初始值。