none
Understanding string on the heap, part 1 RRS feed

  • Question

  • Hi,

    Suppose I have this code:

    public string GetString() { return myStringBuilder.ToString(); }

    public void Go()
    {
    for (int i = 0; i < 10; i++)
    {
    var s = GetString();
    }
    }

    If I run the "Go" method, how many times will I see immutable string content of my StringBuilder on the heap?

    In my head I'd say at least 10 times, but I'm unsure if the "myStringBuilder.ToString();" also makes a separate string on the heap - making the Count 20...or?

    --
    Werner



    Tuesday, October 29, 2013 10:49 AM

Answers

  • Adavesh,  one quick followup question that Google gives different answers to:

    Look at this code:

    string Test(string s)
    {
      // Read s
      return s;
    } void Main() { var s = "1234"; Test(s); }

    There is only one string content on the heap here yes? In other Words, what "Test" receives is a reference to the string right? And it also returns a reference?

    --
    Werner


    Yes. There exists only one string object and you are just passing it's references's here and there. There is one more interesting stuff you might get interested in - String interning. If you have two static string objects as below,

    string a = "Adavesh";
    string b = "Adavesh"

    You might think that there are two string objects but actually there is one. The reason is string interning. You can read my post on string interning to know more about it.

    I hope this helps.


    Please mark this post as answer if it solved your problem. Happy Programming!

    • Marked as answer by Werner Clausen Wednesday, October 30, 2013 2:22 PM
    Wednesday, October 30, 2013 2:00 PM
  • It will create 10 string objects on heap.

    You can verify this by checking memory usage before & after for loops and see the difference.

    public void Go()
    {            
        long initial = GC.GetTotalMemory(true);
    
        for (int i = 0; i < 10; i++)
        {
            var s = GetString();
        }
    
        long final = GC.GetTotalMemory(false);
    
        Console.WriteLine("Usage: " + (final - initial));
    
    }

    I hope this helps.


    Please mark this post as answer if it solved your problem. Happy Programming!

    • Marked as answer by Werner Clausen Wednesday, October 30, 2013 10:09 AM
    Tuesday, October 29, 2013 6:19 PM
  • >There is only one string content on the heap here yes?

    Yes, and here's how to verify that:

    using System;
    
    namespace ConsoleApplication2
    {
      class Program
      {
        static string Test(string s)
        {
          // Read s
          return s;
        }
    
        static void Main()
        {
          var s = "1234";
          var s2 = Test(s);
    
          if (Object.ReferenceEquals(s,s2))
          {
            Console.WriteLine("Same String");
          }
        }
       
      }
    }
    David


    David http://blogs.msdn.com/b/dbrowne/

    • Marked as answer by Werner Clausen Wednesday, October 30, 2013 1:32 PM
    Wednesday, October 30, 2013 1:27 PM

All replies

  • Some more info: I have been reading Eric Lippert’s articles here. But I'm unsure if those articles apply for string also. If it does, the correct answer is 0. They are all on the stack.

    But does that logic go for strings (the value not the reference) also?


    Tuesday, October 29, 2013 11:39 AM
  • It will create 10 string objects on heap.

    You can verify this by checking memory usage before & after for loops and see the difference.

    public void Go()
    {            
        long initial = GC.GetTotalMemory(true);
    
        for (int i = 0; i < 10; i++)
        {
            var s = GetString();
        }
    
        long final = GC.GetTotalMemory(false);
    
        Console.WriteLine("Usage: " + (final - initial));
    
    }

    I hope this helps.


    Please mark this post as answer if it solved your problem. Happy Programming!

    • Marked as answer by Werner Clausen Wednesday, October 30, 2013 10:09 AM
    Tuesday, October 29, 2013 6:19 PM
  • Interesting.

    This Means that "myStringBuilder.ToString();" returns a reference to the string, and this reference is stored in the stack, while the actual string value is in heap.

    Thanks.

    Wednesday, October 30, 2013 10:13 AM
  • Adavesh,  one quick followup question that Google gives different answers to:

    Look at this code:

    string Test(string s)
    {
      // Read s
      return s;
    } void Main() { var s = "1234"; Test(s); }

    There is only one string content on the heap here yes? In other Words, what "Test" receives is a reference to the string right? And it also returns a reference?

    --
    Werner


    Wednesday, October 30, 2013 1:19 PM
  • >There is only one string content on the heap here yes?

    Yes, and here's how to verify that:

    using System;
    
    namespace ConsoleApplication2
    {
      class Program
      {
        static string Test(string s)
        {
          // Read s
          return s;
        }
    
        static void Main()
        {
          var s = "1234";
          var s2 = Test(s);
    
          if (Object.ReferenceEquals(s,s2))
          {
            Console.WriteLine("Same String");
          }
        }
       
      }
    }
    David


    David http://blogs.msdn.com/b/dbrowne/

    • Marked as answer by Werner Clausen Wednesday, October 30, 2013 1:32 PM
    Wednesday, October 30, 2013 1:27 PM
  • Adavesh,  one quick followup question that Google gives different answers to:

    Look at this code:

    string Test(string s)
    {
      // Read s
      return s;
    } void Main() { var s = "1234"; Test(s); }

    There is only one string content on the heap here yes? In other Words, what "Test" receives is a reference to the string right? And it also returns a reference?

    --
    Werner


    Yes. There exists only one string object and you are just passing it's references's here and there. There is one more interesting stuff you might get interested in - String interning. If you have two static string objects as below,

    string a = "Adavesh";
    string b = "Adavesh"

    You might think that there are two string objects but actually there is one. The reason is string interning. You can read my post on string interning to know more about it.

    I hope this helps.


    Please mark this post as answer if it solved your problem. Happy Programming!

    • Marked as answer by Werner Clausen Wednesday, October 30, 2013 2:22 PM
    Wednesday, October 30, 2013 2:00 PM
  • By the way, in order to optimize the memory usage in this particular case, try the next implementation:

    public string GetString()
    {
        return string.Intern( sb.ToString() );
    }


    • Edited by Viorel_MVP Wednesday, October 30, 2013 7:12 PM
    Wednesday, October 30, 2013 7:11 PM
  • Viorel_ [MVP] wrote:

    By the way, in order to optimize the memory usage in this particular case, try the next implementation:

    public string GetString()
    {
             return string.Intern( sb.ToString() );
    }

    Note that this will actually create one extra string over the original. String.Intern will make an interned string in the first call, and return it in subsequent ones - but - it can't get to that string until after you've called sb.ToString(), which still creates the 10 strings. Now, instead of 10 strings on the heap, you end up with 11 (10 + 1 interned string)...


    Reed Copsey, Jr. - http://reedcopsey.com - If a post answers your question, please click Mark As Answer on that post. If you find a post helpful, please click Vote as Helpful.
    Thursday, October 31, 2013 6:42 PM
    Moderator