首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用stackalloc分配的内存初始化

用stackalloc分配的内存初始化
EN

Stack Overflow用户
提问于 2011-12-30 11:37:11
回答 2查看 2.2K关注 0票数 14

如果我用stackalloc在C#中分配内存,那么就是初始化了的内存(使用)

文档没有提到这一点,只告诉您正确的金额是保留的。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-30 11:44:17

从规范中:

18.8堆栈分配 未定义新分配内存的内容。

票数 16
EN

Stack Overflow用户

发布于 2018-11-06 14:30:57

是的,规范说它是未定义的,但是编译器会为stackalloc发出stackalloc的CIL导入。这就是ECMA规范中关于localloc的内容。

localloc指令从本地动态内存池分配大小(类型为本机无符号int)字节,并返回第一个分配字节的地址(托管指针,类型&)。只有当方法上的初始化标志为true时,返回的内存块才被初始化为0(参见Partition )。内存区域是新分配的。当当前方法返回时,本地内存池可以重用。

编译器为每个方法发出初始化标志(也称为localsinit标志),因为它是可验证代码所必需的。

请查看内核上的本期,要求停止对stackalloc上的内存进行零化。在问题的最后,jkotas说:

目前的计划是: 默认情况下,C#将保持零初始化。更改默认设置太坏了。我们打开了一组问题,以使JIT完成的零初始化更有效或减少对它的需求(#13827、#13823、#13825) --那些真正想通过避免零初始化获得最后一点性能的人在知道自己正在做什么时,可以使用自定义的ILLinker步骤(mono/linker#159)。我们今天为CoreLib这样做(通过VM攻击,但我们应该切换到ILLinker),我们计划在CoreFX (dotnet/corefx#25956)中进行实验。根据这些实验的结果,我们可以考虑在将来采用一种更精简的方法来实现这一点。@ahsonkhan,如果你相信它会有帮助的话,你也应该考虑在CoreFXLab中进行它的实验。

看看这个夏普兰的提案

因此得出的结论是:在实际的中将内存初始化为零。

但是,编译器中存在一个错误/特性,可以防止发出localsinit标志。不安全的方法如果不声明其他变量,并且只使用堆栈分配的变量将其传递给其他方法,则不要使用localsinit标志进行标记。

下面是这样一个bug/特性的示例:

代码语言:javascript
复制
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace InformalTests
{

    class Program
    {
        const int n = 100_000_000;

        static unsafe void Main(string[] args)
        {
            var watch = Stopwatch.StartNew();
            for (int i =0; i < n; i++)
            {
                ThisMethodDoes_NOT_InitializeStackAllocatedMemory();
            }
            watch.Stop();
            Console.WriteLine($"NOT INITIALIZED elapsed time {watch.Elapsed}");

            watch.Restart();
            for (int i = 0; i < n; i++)
            {
                ThisMethodInitializeStackAllocatedMemory();
            }
            watch.Stop();
            Console.WriteLine($"INITIALIZED Elapsed time {watch.Elapsed}");
        }


        private static unsafe string ThisMethodDoes_NOT_InitializeStackAllocatedMemory()
        {
            // avoid declaring other local vars, or doing work with stackalloc
            // to prevent the .locals init cil flag , see: https://github.com/dotnet/coreclr/issues/1279
            char* pointer = stackalloc char[256];
            return CreateString(pointer, 256);
        }

        private static unsafe string ThisMethodInitializeStackAllocatedMemory()
        {
            //Declaring a variable other than the stackallocated, causes
            //compiler to emit .locals int cil flag, so it's slower
            int i = 256;
            char* pointer = stackalloc char[256];
            return CreateString(pointer, i);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static unsafe string CreateString(char* pointer, int length)
        {
            return "";
        }
    }
}

未初始化的方法比初始化的方法快5倍。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8679052

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档