Blue Theme Orange Theme Green Theme Red Theme
 
Home | Forums | Videos | Photos | Downloads | Blogs | Interviews | Jobs | Beginners | Training
 | Consulting  
Submit an Article Submit a Blog 
 Login Close
User Id:
Password:
 
Forgot Password
Forgot Username
Why Register
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
 Resources  
Close
 Our Network  
Close
Search :       Advanced Search »
Home » General » C# Heap(ing) Vs Stack(ing) in .NET: Part I

C# Heap(ing) Vs Stack(ing) in .NET: Part I

Even though with the .NET framework we don't have to actively worry about memory management and garbage collection (GC), we still have to keep memory management and GC in mind in order to optimize the performance of our applications.

Author Rank:
Total page views :  212465
Total downloads :  1241
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
Download Files:
StackVsHeap_Part1.zip
 
Become a Sponsor

Even though with the .NET framework we don't have to actively worry about memory management and garbage collection (GC), we still have to keep memory management and GC in mind in order to optimize the performance of our applications. Also, having a basic understanding of how memory management works will help explain the behavior of the variables we work with in every program we write.  In this article I'll cover the basics of the Stack and Heap, types of variables and why some variables work as they do.

There are two places the .NET framework stores items in memory as your code executes.  If you haven't already met, let me introduce you to the Stack and the Heap.  Both the stack and heap help us run our code.  They reside in the operating memory on our machine and contain the pieces of information we need to make it all happen.

Stack vs. Heap: What's the difference?

The Stack is more or less responsible for keeping track of what's executing in our code (or what's been "called").  The Heap is more or less responsible for keeping track of our objects (our data, well... most of it - we'll get to that later.).

Think of the Stack as a series of boxes stacked one on top of the next.  We keep track of what's going on in our application by stacking another box on top every time we call a method (called a Frame).  We can only use what's in the top box on the stack.  When we're done with the top box (the method is done executing) we throw it away and proceed to use the stuff in the previous box on the top of the stack. The Heap is similar except that its purpose is to hold information (not keep track of execution most of the time) so anything in our Heap can be accessed at  any time.  With the Heap, there are no constraints as to what can be accessed like in the stack.  The Heap is like the heap of clean laundry on our bed that we have not taken the time to put away yet - we can grab what we need quickly.  The Stack is like the stack of shoe boxes in the closet where we have to take off the top one to get to the one underneath it.

 

The picture above, while not really a true representation of what's happening in memory, helps us distinguish a Stack from a Heap.
 
The Stack is self-maintaining, meaning that it basically takes care of its own memory management.  When the top box is no longer used, it's thrown out.  The Heap, on the other hand, has to worry about Garbage collection (GC) - which deals with how to keep the Heap clean (no one wants dirty laundry laying around... it stinks!).

What goes on the Stack and Heap?

We have four main types of things we'll be putting in the Stack and Heap as our code is executing: Value Types, Reference Types, Pointers, and Instructions. 

Value Types:

In C#, all the "things" declared with the following list of type declarations are Value types (because they are from System.ValueType):

  • bool
  • byte
  • char
  • decimal
  • double
  • enum
  • float
  • int
  • long
  • sbyte
  • short
  • struct
  • uint
  • ulong
  • ushort

Reference Types:

All the "things" declared with the types in this list are Reference types (and inherit from System.Object... except, of course, for object which is the System.Object object):

  • class
  • interface
  • delegate
  • object
  • string

Pointers:

The third type of "thing" to be put in our memory management scheme is a Reference to a Type. A Reference is often referred to as a Pointer.  We don't explicitly use Pointers, they are managed by the Common Language Runtime (CLR). A Pointer (or Reference) is different than a Reference Type in that when we say something is a Reference Type is means we access it through a Pointer.  A Pointer is a chunk of space in memory that points to another space in memory.  A Pointer takes up space just like any other thing that we're putting in the Stack and Heap and its value is either a memory address or null. 

 

Instructions:

You'll see how the  "Instructions" work later in this article...

How is it decided what goes where? (Huh?)

Ok, one last thing and we'll get to the fun stuff.

Here are our two golden rules:

  1. A Reference Type always goes on the Heap - easy enough, right? 

  2. Value Types and Pointers always go where they were declared.  This is a little more complex and needs a bit more understanding of how the Stack works to figure out where "things" are declared.

The Stack, as we mentioned earlier, is responsible for keeping track of where each thread is during the execution of our code (or what's been called).  You can think of it as a thread "state" and each thread has its own stack.  When our code makes a call to execute a method the thread starts executing the instructions that have been JIT compiled and live on the method table, it also puts  the method's parameters on the thread stack.  Then, as we go through the code and run into variables within the method they are placed on top of the stack.  This will be easiest to understand by example...

Take the following method.

           public int AddFive(int pValue)
          {
                int result;
                result = pValue + 5;
               
return result;
          }

Here's what happens at the very top of the stack.  Keep in mind that what we are looking at is placed on top of many other items already living in the stack:

Once we start executin ghte method, the method's parameters are placed on the stack (we'll talk more about passing parameters later).

NOTE : the method does not live on the stack and is illustrated just for reference.

 

Next, control (the thread executing the method) is passed to the instructions to the AddFive() method which lives in our type's method table, a JIT compilation is performed if this is the first time we are hitting the method.

 

As the method executes, we need some memory for the "result" variable and it is allocated on the stack.

 

The method finishes execution and our result is returned.

 

And all memory allocated on the stack is cleaned up by moving a pointer to the available memory address where AddFive() started and we go down to the previous method on the stack (not seen here).

In this example, our "result" variable is placed on the stack.  As a matter of fact, every time a Value Type is declared within the body of a method, it will be placed on the stack.

Now, Value Types are also sometimes placed on the Heap.  Remember the rule, Value Types always go where they were declared?  Well, if a Value Type is declared outside of a method, but inside a Reference Type it will be placed within the Reference Type on the Heap.

Here's another example.

If we have the following MyInt class (which is a Reference Type because it is a class):

          public class MyInt
          {         
            
public int MyValue;
          }

and the following method is executing:

          public MyInt AddFive(int pValue)
          {
                MyInt result = new MyInt();
                result.MyValue = pValue + 5;
                return result;
          }

Just as before, the thread starts executing the method and its parameters are placed on sthe thread's stack.

Now is when it gets interesting...

Because MyInt is a Reference Type, it is placed on the Heap and referenced by a Pointer on the Stack.

After AddFive() is finished executing (like in the first example), and we are cleaning up...

we're left with an orphaned MyInt in the heap (there is no longer anyone in the Stack standing around pointing to MyInt)!

This is where the Garbage Collection (GC) comes into play.  Once our program reaches a certain memory threshold and we need more Heap space, our GC will kick off.  The GC will stop all running threads (a FULL STOP), find all objects in the Heap that are not being accessed by the main program and delete them.  The GC will then reorganize all the objects left in the Heap to make space and adjust all the Pointers to these objects in both the Stack and the Heap.  As you can imagine, this can be quite expensive in terms of performance, so now you can see why it can be important to pay attention to what's in the Stack and Heap when trying to write high-performance code.

Ok... That great, but how does it really affect me?

Good question. 

When we are using Reference Types, we're dealing with Pointers to the type, not the thing itself.  When we're using Value Types, we're using the thing itself.  Clear as mud, right?

Again, this is best described by example.

If we execute the following method:

          public int ReturnValue()
          {
                int x = new int();
                x = 3;
                int y = new int();
                y = x;      
                y = 4;         
               
return x;
    
      }

We'll get the value 3.  Simple enough, right?

However, if we are using the MyInt class from before

     public class MyInt
          {

                public int MyValue;
          }

and we are executing the following method:

          public int ReturnValue2()
          {
                MyInt x = new MyInt();
                x.MyValue = 3;
                MyInt y = new MyInt();
                y = x;                 
                y.MyValue = 4;              
                
return x.MyValue;
          }

What do we get?...    4!

Why?...  How does x.MyValue get to be 4?... Take a look at what we're doing and see if it makes sense:

In the first example everything goes as planned:

          public int ReturnValue()
          {
                int x = 3;
                int y = x;    
                y = 4;
               
return x;
          }

In the next example, we don't get "3" because both variables "x" and "y" point to the same object in the Heap.

          public int ReturnValue2()
          {
                MyInt x;
                x.MyValue = 3;
                MyInt y;
                y = x;                
                y.MyValue = 4;
                
return x.MyValue;
          }

Hopefully this gives you a better understanding of a basic difference between Value Type and Reference Type variables in C# and a basic understanding of what a Pointer is and when it is used.  In the next part of this series, we'll get further into memory management and specifically talk about method parameters.

For now...

Happy coding.

Part I | Part II | Part III | Part IV


Login to add your contents and source code to this article
 About the author
 
Matthew Cochran
Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Go.NET
Build custom interactive diagrams, network, workflow editors, flowcharts, or software design tools. Includes many predefined kinds of nodes, links, and basic shapes. Supports layers, scrolling, zooming, selection, drag-and-drop, clipboard, in-place editing, tooltips, grids, printing, overview window, palette. 100% implemented in C# as a managed .NET Control. Document/View/Tool architecture with many properties&events. Optional automatic layout.
Dundas Software
Dundas Chart for .NET is the most advanced .NET charting package available today.  With an extremely complete feature set, elegant architecture and easy implementation, Dundas Chart can quickly add advanced Charting functionality to enhance and transform ASP.NET and Windows Forms applications.  Whether you are implementing charting into internal projects, or building applications for clients, Dundas Chart offers advanced technology and advanced results to get the most out of data.
Clickatell's SMS Gateway
Clickatell's Developer Solutions allow you to SMS enable any website or application via a range of API's. Learn More about our API connections.
Free access to .NET Memory Management video
Everything you need to know about Garbage Collection, Temporary Objects, Fragmentation, Finalization and common causes of memory leaks in .NET. Watch the video here.
Microsoft Visual Studio 2010 Professional
Microsoft Visual Studio 2010 Professional will launch on April 12, but you can beat the rush and secure your copy today by pre-ordering at the affordable estimated retail price of $549 (US). Pre-order now.
Nevron Chart for .NET 2010.1 Now Available
The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
Developer-Ready ASP.NET 2.0 Web Hosting with 3 MONTHS FREE
Now supporting .NET 3.0 Framework with Windows Workflow Foundation, Windows Communication Foundation (WCF), Windows Presentation Foundation (WPF), windows CardSpace (WCS)! Providing more flexibility for Developers with Web Services Support and a User/Permission Manger. Also supporting MS SQL 2005/2000 with Real-Time Backups, FREE Automated Attach .MDF Tool, FREE SQL Restore and Shrink SQL DB Tools, and SQL
 
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
Download Files:
StackVsHeap_Part1.zip
 
 Post a Feedback, Comment, or Question about this article
Subject:  
Comment:  
Become a Sponsor
 Comments
Illustrative example by B On February 8, 2006
I made a snippet of code that illustrates how a stuct handles delegates differently than a class. Run the code, then change the declaration 'public struct testStruct' to a class and you get the opposite result. Apparently, in a struct, test is stored by value instead of by reference, thus changes are lost. Any comment appreciated since I am still trying to make sense of this article:
 

using System;
namespace HeapVsStack
{
 class HeapVsStack
 {
  delegate void aDelegate();
  struct testBlock //DIFFERENT RESULT with: class testBlock
  {
   bool test;
   public testBlock(int x)
   {
    test = true;
    MakeTestFalseWithDelegate(new aDelegate(MakeTestFalse));
    System.Console.ReadLine();
   }
   void MakeTestFalse()
   {
    Console.WriteLine("Making test false");
    test = false;
   }
   void MakeTestFalseWithDelegate(aDelegate adelegate)
   {
    adelegate();
    Console.WriteLine("delegate result: " + test);
   }
  }

  static void Main(string[] args)
  {
   testBlock t = new testBlock(0);
  }
 }
}

Reply | Email | Delete | Modify | 
Illustrative example by Matthew On February 12, 2006

This is a great question.  It does get into territory a little deeper than I intended to go with this introductory article.  To give a proper explaination of what is happening, I just wrote an article on boxing that deals with the situation you are running into that will go into more detail if you are interested.

In brief, what's happening in your code sample is that the struct is being boxed when the delegate is created.  When we execute the method via. the delegate we are really updating a copy of the object that was boxed to the Heap (we are no longer dealing with the object on the Stack). 

In the case when we use a class instead of the struct, the object lives on the Heap the whole time and we aren't dealing with two objects any more, so we get results more along the lines of what would be expected.

Reply | Email | Delete | Modify | 
.Net doubts by srikanth On October 10, 2006

What is the difference between Response.Redirect and server.Transfer Give me a detailed explanation.and give me the explanation about request.forms and request.QueryString

Reply | Email | Delete | Modify | 
Repeater by srikanth On October 10, 2006
What is the DataRepeater,DataList,DataGrid what is the Main Difference between Both of us. Give me the brief explanation. if i use paging and adding controls to the dataRepeater
Reply | Email | Delete | Modify | 
stack question by dak On January 4, 2007

In the example you have illustrated how does the control go to the AddFive method without popping out the pValue parameter(since pValue is @ the top of the stack)

Reply | Email | Delete | Modify | 
Is 'System.Object obj' an exceptional case? by Anugrah On January 8, 2008
As you have said above that "all reference types are stored on heap except Sytem.Object myObject". Can you provide more details that why instance of class System.Object is not stored on Heap?
Reply | Email | Delete | Modify | 
Re: Is 'System.Object obj' an exceptional case? by Matthew On January 22, 2008
I guess I wasn't that clear when I said

>> "All the "things" declared with the types in this list are Reference types (and inherit from System.Object... except, of course, for object which is the System.Object object):"

System.Object does end up on the heap because it is a reference type, but it does not inherit from System.Object because it IS System.Object (it can't be a supertype of itself).
Reply | Email | Delete | Modify | 
Value Types and Pointers always go where they were declared. by Paul On October 7, 2008
It's nice to see this properly stated!
Reply | Email | Delete | Modify | 
Excellent Explanation.. by Charanjot On January 22, 2009
Thank you very much for giving such a wonderful and excellent explanation about Stack and Heap with examples. I didn't find such a health article about memory management. Thanks a lot....
Reply | Email | Delete | Modify | 
Very Good on by bala On July 6, 2009
Hey its good.
Reply | Email | Delete | Modify | 
Tracking Heap-ing and Stack-ing? by Jeff On August 31, 2009

Hi Matthew Cochran,
 
Is there a way to track specifically how much Stack-ing and Heap-ing is currently in use?

I would like to checkout what is going on within the Stack and Heap (where, what, and how much memory) that is used during a specific event.

Thanks

Reply | Email | Delete | Modify | 
Stack vs Heap awesome article... by Manish On September 12, 2009
Thanks Matthew very good article.
Reply | Email | Delete | Modify | 
Thanks by Tarik On October 15, 2009
Thanks for this really well-written article. It really helped me a lot maybe more than you was expecting during writing. Thanks...
Reply | Email | Delete | Modify | 
Great Article by Luis On February 4, 2010
Thanks Matthew Cochran this is a great and well explained article. the drawings helps a lot to understand.

Keep the good work!
Reply | Email | Delete | Modify | 

 Hosted by MaximumASP  |  Found a broken link?  |  Contact Us  |  Terms & conditions  |  Privacy Policy  |  Site Map  |  Suggest an Idea  |  Media Kit
Current Version: 5.2009.6.2
 © 2010  contents copyright of their authors. Rest everything copyright Mindcracker. All rights reserved.