使用stackalloc分配的内存初始化

时间:2011-12-30 11:37:12

标签: c# unsafe stackalloc

如果我在 C#中使用stackalloc分配内存,是内存已初始化(使用0
文档没有提到这一点,只说明保留了正确的金额。

在我的测试中,这样的内存默认为0,但这并不意味着它得到了保证。

2 个答案:

答案 0 :(得分:14)

来自规范:

  

18.8筹码分配

     

新分配的内存的内容未定义。

答案 1 :(得分:4)

是的,规范说它是未定义的,但是编译器发出localloc的{​​{1}} CIL指令。这就是ECMA规范对stackalloc的评价:

  

localloc指令分配大小(类型为native unsigned int)   本地动态内存池中的字节数并返回地址(   受管指针,输入第一个分配的字节的&)。的块   返回的内存仅在以下位置初始化为0:   方法是正确的(请参阅分区I)。内存区域是新的   已分配。当前方法返回时,本地内存池为   可供重复使用。

由于可验证代码需要初始化标志,也称为localloc标志,它由编译器为每种方法发出。

请查看coreclr上的this issue,要求停止将stackalloc上的内存清零。在问题的结尾,jkotas说:

  

当前计划是:

     

C#默认情况下将保持零初始化。更改默认值将   太破了。我们提出了一系列问题以使零   由JIT完成的初始化更加有效或减少了对它的需求   (#13827,#13823,#13825)真正想得到最后一分的人   通过避免零初始化来提高性能可以使用自定义ILLinker   当他们知道自己在做什么时,执行步骤(mono / linker#159)。我们这样做   今天的CoreLib(通过VM黑客,但我们应该切换到ILLinker),   我们计划在CoreFX(dotnet / corefx#25956)中对此进行试验。   根据这些实验的结果,我们可以考虑引入   将来更简化的方法。 @ahsonkhan你应该   如果您认为,也可以考虑在CoreFXLab中进行实验   会有所帮助。

并查看此csharplang提案

因此结论是:在实践中,内存被初始化为零

但是,编译器中存在一个错误/功能,无法发出localsinit标志。不声明其他变量并且仅将堆栈分配的变量用于将其传递给其他方法的不安全方法,不会用localsinit标志进行标记。

以下是此类错误/功能的示例:

localsinit

未初始化方法比已初始化方法快五倍。