#905 – Examining an Exception’s Stack Trace

When you access an exception object’s StackTrace property from within an exception handler, you only have access to a single multiline string that dumps out details about the stack.

For example:

905-001

This format is not ideal, since it’s fairly verbose and you have no ability to look at individual items within the stack.

If you want more control in formatting output that shows the stack, or you want to programmatically examine the stack, you can create a new System.Diagnostics.StackTrace object, passing it the Exception object that you’re handling.

Below is an example that dumps out a more abbreviated version of the stack and changes the order to match the calling sequence.

                catch (Exception ex)
                {
                    Console.WriteLine("** Caught exception, stack :");
                    StackTrace stack = new StackTrace(ex);
                    StackFrame[] frames = stack.GetFrames();
                    for (int i = frames.Count() - 1; i >= 0; i--)
                    {
                        MethodBase mb = frames[i].GetMethod();
                        Console.WriteLine("- {0}  [{1}]",
                            mb.Name,
                            mb.DeclaringType.FullName);
                    }
                }

905-002

Advertisement

#843 – Using the Generic Stack Class

A stack is a data structure that allows adding elements to the top of the stack through a Push operation, or removing elements from the top of the stack through a Pop operation.

The .NET Framework includes a Stack<T> type, defined in System.Collections.Generic, that implements a stack data type.

When you declare a stack, you indicate the type of objects that the stack will contain.

            Stack<Book> pileOfBooks = new Stack<Book>();

You can now add instances of Books to the top of the stack using the Push method.

            // Push 1st book onto stack
            pileOfBooks.Push(new Book("The World According to Garp", new Person("Irving", "John")));

            // Push another.  Gatsby on "top" of stack
            pileOfBooks.Push(new Book("The Great Gatsby", new Person("Fitzgerald", "F. Scott")));

843-001
You can remove the object from the stop of the stack using the Pop method.

            // Remove book from top
            Book bookToRead = pileOfBooks.Pop();
            Console.WriteLine(bookToRead);

843-002
843-003

#842 – The Stack Data Type

stack is a data type used to store a collection of items and which has the following properties:

  • Elements can be added to the stack 
  • Elements can be removed from the stack, but only in the reverse order from the order in which they were added

Adding an item is known as a Push operation.  Removing an item is known as a Pop operation.

You can think of a stack data type as being like a physical stack of trays.  You can add new trays, but only to the top of the pile (a Push).  You can remove a tray from the stack, but only from the top of the stack (a Pop).

Like a physical stack of trays, we refer to the location of the last item added to the stack as the top of the stack.

A stack is also known as a LIFO (Last-In, First-Out) structure.

842-001

#189 – Memory Management for Stack-Based Objects

When an object is created on the stack, memory is allocated from the stack for that object.

Memory for an object allocated from the stack is not deallocated until the function containing the declaration exits.

        static void Main(string[] args)
        {
            int x = 42;

            SomeMethod();

            // x deallocated when Main() exits
        }

        static void SomeMethod()
        {
            int y = 100;
            int z = 12;
            int sum = y + z;

            // y, z, sum all deallocated when SomeMethod() exits
        }

In practice, you don’t care much when memory for an object is deallocated.  Instead, you care more about the block of code within which you can refer to and use the variable–its scope.

#188 – Objects Are on the Heap, References to Objects Are on the Stack

When you instantiate an object, an area of memory on the heap is allocated to store the object’s data.  So we typically say that the object is on the heap.

            Person thatGuy = new Person("Julius", "Caesar");

In the above example, a new instance of the Person class is created and the data for this Person is stored on the heap.

But in creating a new instance of a Person, we also had to declare and instantiate a reference to the Person object that we just created.  That reference is stored on the stack.

In the same way that value types are normally stored on the stack, but can be on the heap if they exist within another object, object references can also be on the heap if they are contained within other objects.

#186 – Value Types on the Heap

Value types are normally allocated on the stack. They can, however, be allocated on the heap–when they are declared within an object.  When an object is instantiated, memory for the entire object, including all of its data, is allocated on the heap.

For example, assume we define a Person class with some properties that are value types (int) and some that are reference types (string).

    public class Person
    {
        string FirstName;
        string LastName;

        int Age;
        int HeightInInches;      // also on heap

        public Person(string firstName, string lastName)
        {
            FirstName = firstName;
            LastName = lastName;
        }
    }

When you create an instance of the Person object,

            Person p = new Person("Zsa Zsa", "Gabor");

the Person object is created on the heap and all of its data members, including the Age and HeightInInches value types, are also on the heap.

#185 – The Heap and the Stack

In C#, all objects are created on either the heap or the stack.

The stack is an area of memory where the following is stored:

  • Objects whose type is a value type
    • (e.g. enums, built-in types and structs)
  • Values of parameters passed to methods
  • References to objects created on the heap   (aka pointers)

The heap is an area of memory where the following is stored:

  • Objects that are instances of reference types
    • (e.g. strings, arrays, built-in types in the .NET framework, custom types)

Memory for objects created on the stack is allocated when a method is called or when the object is instantiated.  The memory is released when the method that instantiated the object exits.

Memory for objects created on the heap is allocated when the object is instantiated and managed by the CLR garbage collector, which frees memory periodically.