Initialization of memory allocated with stackalloc





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







9















If I'm allocating memory with stackalloc in C#, is that memory initialized (with 0)?

The documentation doesn't speak of that and only tells that the correct amount is reserved.



In my tests such memory defaulted to 0, but that doesn't mean it's guaranteed though.










share|improve this question





























    9















    If I'm allocating memory with stackalloc in C#, is that memory initialized (with 0)?

    The documentation doesn't speak of that and only tells that the correct amount is reserved.



    In my tests such memory defaulted to 0, but that doesn't mean it's guaranteed though.










    share|improve this question

























      9












      9








      9


      2






      If I'm allocating memory with stackalloc in C#, is that memory initialized (with 0)?

      The documentation doesn't speak of that and only tells that the correct amount is reserved.



      In my tests such memory defaulted to 0, but that doesn't mean it's guaranteed though.










      share|improve this question














      If I'm allocating memory with stackalloc in C#, is that memory initialized (with 0)?

      The documentation doesn't speak of that and only tells that the correct amount is reserved.



      In my tests such memory defaulted to 0, but that doesn't mean it's guaranteed though.







      c# unsafe stackalloc






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 30 '11 at 11:37









      frumbaelafrumbaela

      1866




      1866
























          2 Answers
          2






          active

          oldest

          votes


















          14














          From the spec:




          18.8 Stack allocation



          The content of the newly allocated memory is undefined.







          share|improve this answer
























          • Now that the stackalloc can be used in "safe" context with Span<T>, does this still hold true?

            – JBeurer
            Jan 1 at 21:39



















          3














          Yes, the spec says it is undefined, but the compiler emits localloc CIL intruction for stackalloc. And this is what ECMA Specs says about localloc:




          The localloc instruction allocates size (type native unsigned int)
          bytes from the local dynamic memory pool and returns the address (a
          managed pointer, type &) of the first allocated byte. The block of
          memory returned is initialized to 0 only if the initialize flag on the
          method is true (see Partition I). The area of memory is newly
          allocated. When the current method returns the local memory pool is
          available for reuse.




          The initialize flag, also known as localsinit flag, is emitted for every method by the compiler because it is required for verifiable code.



          Please look at this issue on coreclr asking to stop zeroing memory on stackalloc. At the end of the issue jkotas says:




          The current plan is:



          C# will keep zero initializing by default. Changing the default would
          be too breaking. We have a set of issues opened to make the zero
          initialization done by the JIT more efficient or reduce need for it
          (#13827, #13823, #13825) Folks who really want to get the last bit of
          performance by avoiding zero initialization can use custom ILLinker
          step (mono/linker#159) when they know what they are doing. We do this
          for CoreLib today (via VM hack, but we should switch to the ILLinker),
          and we plan to experiment with this in CoreFX (dotnet/corefx#25956).
          Based on the results of these experiments, we may consider introducing
          a more streamlined way to do this in future. @ahsonkhan You should
          consider experimenting with it in CoreFXLab as well if you believe
          that it would help.




          And see this csharplang proposal



          So the conclusion is: the memory is initialized to zero in practice



          However there is a bug/feature in the compiler that prevents from emiting localsinit flag. Unsafe methods that don't declare other variables and use the stack allocated variable only to passing it to other method, don't get marked with the localsinit flag.



          Here is an example of such bug/feature:



          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 "";
          }
          }
          }


          The not initialized method is five times faster than the initialized one.






          share|improve this answer


























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f8679052%2finitialization-of-memory-allocated-with-stackalloc%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            14














            From the spec:




            18.8 Stack allocation



            The content of the newly allocated memory is undefined.







            share|improve this answer
























            • Now that the stackalloc can be used in "safe" context with Span<T>, does this still hold true?

              – JBeurer
              Jan 1 at 21:39
















            14














            From the spec:




            18.8 Stack allocation



            The content of the newly allocated memory is undefined.







            share|improve this answer
























            • Now that the stackalloc can be used in "safe" context with Span<T>, does this still hold true?

              – JBeurer
              Jan 1 at 21:39














            14












            14








            14







            From the spec:




            18.8 Stack allocation



            The content of the newly allocated memory is undefined.







            share|improve this answer













            From the spec:




            18.8 Stack allocation



            The content of the newly allocated memory is undefined.








            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Dec 30 '11 at 11:44









            user703016user703016

            31.4k676102




            31.4k676102













            • Now that the stackalloc can be used in "safe" context with Span<T>, does this still hold true?

              – JBeurer
              Jan 1 at 21:39



















            • Now that the stackalloc can be used in "safe" context with Span<T>, does this still hold true?

              – JBeurer
              Jan 1 at 21:39

















            Now that the stackalloc can be used in "safe" context with Span<T>, does this still hold true?

            – JBeurer
            Jan 1 at 21:39





            Now that the stackalloc can be used in "safe" context with Span<T>, does this still hold true?

            – JBeurer
            Jan 1 at 21:39













            3














            Yes, the spec says it is undefined, but the compiler emits localloc CIL intruction for stackalloc. And this is what ECMA Specs says about localloc:




            The localloc instruction allocates size (type native unsigned int)
            bytes from the local dynamic memory pool and returns the address (a
            managed pointer, type &) of the first allocated byte. The block of
            memory returned is initialized to 0 only if the initialize flag on the
            method is true (see Partition I). The area of memory is newly
            allocated. When the current method returns the local memory pool is
            available for reuse.




            The initialize flag, also known as localsinit flag, is emitted for every method by the compiler because it is required for verifiable code.



            Please look at this issue on coreclr asking to stop zeroing memory on stackalloc. At the end of the issue jkotas says:




            The current plan is:



            C# will keep zero initializing by default. Changing the default would
            be too breaking. We have a set of issues opened to make the zero
            initialization done by the JIT more efficient or reduce need for it
            (#13827, #13823, #13825) Folks who really want to get the last bit of
            performance by avoiding zero initialization can use custom ILLinker
            step (mono/linker#159) when they know what they are doing. We do this
            for CoreLib today (via VM hack, but we should switch to the ILLinker),
            and we plan to experiment with this in CoreFX (dotnet/corefx#25956).
            Based on the results of these experiments, we may consider introducing
            a more streamlined way to do this in future. @ahsonkhan You should
            consider experimenting with it in CoreFXLab as well if you believe
            that it would help.




            And see this csharplang proposal



            So the conclusion is: the memory is initialized to zero in practice



            However there is a bug/feature in the compiler that prevents from emiting localsinit flag. Unsafe methods that don't declare other variables and use the stack allocated variable only to passing it to other method, don't get marked with the localsinit flag.



            Here is an example of such bug/feature:



            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 "";
            }
            }
            }


            The not initialized method is five times faster than the initialized one.






            share|improve this answer






























              3














              Yes, the spec says it is undefined, but the compiler emits localloc CIL intruction for stackalloc. And this is what ECMA Specs says about localloc:




              The localloc instruction allocates size (type native unsigned int)
              bytes from the local dynamic memory pool and returns the address (a
              managed pointer, type &) of the first allocated byte. The block of
              memory returned is initialized to 0 only if the initialize flag on the
              method is true (see Partition I). The area of memory is newly
              allocated. When the current method returns the local memory pool is
              available for reuse.




              The initialize flag, also known as localsinit flag, is emitted for every method by the compiler because it is required for verifiable code.



              Please look at this issue on coreclr asking to stop zeroing memory on stackalloc. At the end of the issue jkotas says:




              The current plan is:



              C# will keep zero initializing by default. Changing the default would
              be too breaking. We have a set of issues opened to make the zero
              initialization done by the JIT more efficient or reduce need for it
              (#13827, #13823, #13825) Folks who really want to get the last bit of
              performance by avoiding zero initialization can use custom ILLinker
              step (mono/linker#159) when they know what they are doing. We do this
              for CoreLib today (via VM hack, but we should switch to the ILLinker),
              and we plan to experiment with this in CoreFX (dotnet/corefx#25956).
              Based on the results of these experiments, we may consider introducing
              a more streamlined way to do this in future. @ahsonkhan You should
              consider experimenting with it in CoreFXLab as well if you believe
              that it would help.




              And see this csharplang proposal



              So the conclusion is: the memory is initialized to zero in practice



              However there is a bug/feature in the compiler that prevents from emiting localsinit flag. Unsafe methods that don't declare other variables and use the stack allocated variable only to passing it to other method, don't get marked with the localsinit flag.



              Here is an example of such bug/feature:



              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 "";
              }
              }
              }


              The not initialized method is five times faster than the initialized one.






              share|improve this answer




























                3












                3








                3







                Yes, the spec says it is undefined, but the compiler emits localloc CIL intruction for stackalloc. And this is what ECMA Specs says about localloc:




                The localloc instruction allocates size (type native unsigned int)
                bytes from the local dynamic memory pool and returns the address (a
                managed pointer, type &) of the first allocated byte. The block of
                memory returned is initialized to 0 only if the initialize flag on the
                method is true (see Partition I). The area of memory is newly
                allocated. When the current method returns the local memory pool is
                available for reuse.




                The initialize flag, also known as localsinit flag, is emitted for every method by the compiler because it is required for verifiable code.



                Please look at this issue on coreclr asking to stop zeroing memory on stackalloc. At the end of the issue jkotas says:




                The current plan is:



                C# will keep zero initializing by default. Changing the default would
                be too breaking. We have a set of issues opened to make the zero
                initialization done by the JIT more efficient or reduce need for it
                (#13827, #13823, #13825) Folks who really want to get the last bit of
                performance by avoiding zero initialization can use custom ILLinker
                step (mono/linker#159) when they know what they are doing. We do this
                for CoreLib today (via VM hack, but we should switch to the ILLinker),
                and we plan to experiment with this in CoreFX (dotnet/corefx#25956).
                Based on the results of these experiments, we may consider introducing
                a more streamlined way to do this in future. @ahsonkhan You should
                consider experimenting with it in CoreFXLab as well if you believe
                that it would help.




                And see this csharplang proposal



                So the conclusion is: the memory is initialized to zero in practice



                However there is a bug/feature in the compiler that prevents from emiting localsinit flag. Unsafe methods that don't declare other variables and use the stack allocated variable only to passing it to other method, don't get marked with the localsinit flag.



                Here is an example of such bug/feature:



                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 "";
                }
                }
                }


                The not initialized method is five times faster than the initialized one.






                share|improve this answer















                Yes, the spec says it is undefined, but the compiler emits localloc CIL intruction for stackalloc. And this is what ECMA Specs says about localloc:




                The localloc instruction allocates size (type native unsigned int)
                bytes from the local dynamic memory pool and returns the address (a
                managed pointer, type &) of the first allocated byte. The block of
                memory returned is initialized to 0 only if the initialize flag on the
                method is true (see Partition I). The area of memory is newly
                allocated. When the current method returns the local memory pool is
                available for reuse.




                The initialize flag, also known as localsinit flag, is emitted for every method by the compiler because it is required for verifiable code.



                Please look at this issue on coreclr asking to stop zeroing memory on stackalloc. At the end of the issue jkotas says:




                The current plan is:



                C# will keep zero initializing by default. Changing the default would
                be too breaking. We have a set of issues opened to make the zero
                initialization done by the JIT more efficient or reduce need for it
                (#13827, #13823, #13825) Folks who really want to get the last bit of
                performance by avoiding zero initialization can use custom ILLinker
                step (mono/linker#159) when they know what they are doing. We do this
                for CoreLib today (via VM hack, but we should switch to the ILLinker),
                and we plan to experiment with this in CoreFX (dotnet/corefx#25956).
                Based on the results of these experiments, we may consider introducing
                a more streamlined way to do this in future. @ahsonkhan You should
                consider experimenting with it in CoreFXLab as well if you believe
                that it would help.




                And see this csharplang proposal



                So the conclusion is: the memory is initialized to zero in practice



                However there is a bug/feature in the compiler that prevents from emiting localsinit flag. Unsafe methods that don't declare other variables and use the stack allocated variable only to passing it to other method, don't get marked with the localsinit flag.



                Here is an example of such bug/feature:



                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 "";
                }
                }
                }


                The not initialized method is five times faster than the initialized one.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 25 '18 at 10:03

























                answered Nov 6 '18 at 14:30









                Jesús LópezJesús López

                4,28411542




                4,28411542






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f8679052%2finitialization-of-memory-allocated-with-stackalloc%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    Academy of Television Arts & Sciences

                    L'Équipe

                    1995 France bombings