为什么在.Net 4.5中更改了内存初始化规则?

时间:2013-09-29 17:34:58

标签: .net cil il

更新我的一些代码示例以进行培训我注意到之前由 CLR 保持未初始化的一些本地内存现在归零

这是一个小的 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 个答案:

答案 0 :(得分:2)

这只是一个巧合,没有任何故意清除你的当地人。抖动会尝试将本地保留在寄存器中,如果不需要,它甚至不会分配堆栈空间。你的程序很小,当你不用/ 32bitpreferred标志编译它时,它选择一个本地寄存器的好处很好,这个寄存器以前没有在当前线程上使用过,但仍然没有值。你可以在以下时收回垃圾:

  • 使用/ 32bitpreferred标志编译代码。 32位代码具有较少的寄存器,因此您的本地可能存储在脏堆栈或脏寄存器中。
  • 为您的值类型创建更多字段,或使用更多本地,因此它们不适合寄存器集,或者抖动不会选择将它们存储在那里。
  • 在您的方法中做更多涉及寄存器的事情

我不确定为什么你需要在版本4.5中找到与以前版本相比未经初始化的值。也许这是抖动中某些变化的副作用,但我只是在猜测。关键是你仍然需要你的本地人的init标志,以确保他们得到零初始值。