#920 – A finally Block Is Not Executed When a Corrupted State Exception Occurs

When a corrupted state exception occurs as a result of executing some code within a try block, code within an associated finally block is not executed.  This is true whether or not you use the HandleProcessCorruptedStateExceptions attribute to indicate that you want to catch corrupted state exceptions.

In the example below, we execute some code that causes an access violation and a corrupted state exception occurs.  We do catch the CSE, but the code within our finally block is never executed.

        [HandleProcessCorruptedStateExceptions]
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Before call to CausesAccessViolation()");
                CausesAccessViolation();
                Console.WriteLine("Before call to CausesAccessViolation()");
            }
            catch (Exception exc)
            {
                Console.WriteLine(string.Format("Hey, I caught an Exception: {0}", exc.ToString()));
            }

            Console.ReadLine();
        }

        static void CausesAccessViolation()
        {
            try
            {
                IntPtr ptr = new IntPtr(123);
                Marshal.StructureToPtr(123, ptr, true);
            }
            finally
            {
                Console.WriteLine("* finally block in CausesAccessViolation() executing");
            }
        }

920-001

#919 – Think Twice about Handling Corrupted State Exceptions

Corrupted State Exceptions are exceptions that indicate that the memory state of the current process is likely corrupt.  These CSEs by default cannot be caught by your code.  This is normally what you want, since you typically don’t want to continue execution when one of these exceptions occurs.  You can, however, use the HandleProcessCorruptedStateExceptions attribute to indicate that you do want to handle CSEs.

Be very careful when handling Corrupted State Exceptions.  When an exception in this category is thrown, there is a good chance that the memory space of your process is corrupt.  Continuing execution may lead to unpredictable behavior and could even cause other data to become corrupt.

If you do catch Corrupted State Exceptions, you should execute as little code as possible and exit your application as soon as possible.  You might, for example, just log the fact that the CSE occurred and then exit.

#918 – Catching Corrupted State Exceptions

Corrupted State Exceptions are exceptions that indicate that the memory state of the current process is likely corrupt.  These CSEs by default cannot be caught by your code.  This is normally what you want, since you typically don’t want to continue execution when one of these exceptions occurs.

You can, however, set an attribute on a method indicating that you do want to catch Corrupted State Exceptions.  If you set the HandleProcessCorruptedStateExceptions attribute on a method, it will then be able to catch this category of exceptions.

In the example below, we are able to catch the access violation exception.

        [HandleProcessCorruptedStateExceptions]
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Before call to CausesAccessViolation()");
                CausesAccessViolation();
                Console.WriteLine("Before call to CausesAccessViolation()");
            }
            catch (Exception exc)
            {
                Console.WriteLine(string.Format("Hey, I caught an Exception: {0}", exc.ToString()));
            }

            Console.ReadLine();
        }

        static void CausesAccessViolation()
        {
            IntPtr ptr = new IntPtr(123);
            Marshal.StructureToPtr(123, ptr, true);
        }

918-001

#917 – Corrupted State Exceptions Are Not Normally Caught

Starting with .NET 4.0, there are a class of exceptions that will not be caught within a general catch block that catches all exceptions deriving from System.Exception.  By default, a corrupted state exception will not be caught as a System.Exception.  A corrupted state exception is a type of exception, like an access violation, that likely results in the internal state of the process being corrupt.

In the example below, we artificially generate an access violation.  Note that the exception that is raised is not caught, but treated as an unhandled exception.  (Our catch block never executes).

        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Before call to CausesAccessViolation()");
                CausesAccessViolation();
                Console.WriteLine("Before call to CausesAccessViolation()");
            }
            catch (Exception exc)
            {
                Console.WriteLine(string.Format("Hey, I caught an Exception: {0}", exc.ToString()));
            }

            Console.ReadLine();
        }

        static void CausesAccessViolation()
        {
            IntPtr ptr = new IntPtr(123);
            Marshal.StructureToPtr(123, ptr, true);
        }

917-001

#916 – Exception Can Cross .NET Language Boundaries

An exception being thrown from one assembly can be caught in a different assembly.  This is true even when the assemblies are authored in different .NET languages.

Below, code in the ConsoleApplication2 assembly, which is written in Visual Basic, calls code in the DogLibrary assembly (the Dog.Bark method), which is written in C#.  When an exception originates in DogLibrarywe can catch it in the code running in ConsoleApplication2.

916-001

Assume that the code in DogLibrary looks like:

        public void Bark(int numTimes)
        {
            if (numTimes > 10)
                throw new ApplicationException("Too many times to bark");

            for (int i = 0; i < numTimes; i++)
                Console.WriteLine("Woof");
        }

And the code in ConsoleApplication2 looks like:

    Sub Main()
        Try
            Dim d As Dog = New Dog("Bowser")
            d.Bark(100)

        Catch ex As Exception
            Console.WriteLine(String.Format("Uh-oh! {0}", ex.ToString()))
        End Try
    End Sub

We can catch the exception in the VB code that was thrown by the C# code.
916-002

#915 – An Exception Can Cross Assembly Boundaries

If code within one assembly calls code within another assembly, exceptions originating within the code being called can bubble up to the calling code.  The exception can be thrown from one assembly and caught in another.

Below, code in the ConsoleApplication1 assembly calls code in the DogLibrary assembly (the Dog.Bark method).  When an exception originates in DogLibrary, we can catch it in the code running in ConsoleApplication1.

915-001

Code in ConsoleApplication1:

            try
            {
                Dog d = new Dog("Bowser");
                d.Bark(100);
            }
            catch (ApplicationException exc)
            {
                Console.WriteLine(exc.ToString());
            }

Code in DogLibrary:

    public class Dog
    {
        public string Name { get; set; }

        public Dog(string name)
        {
            Name = name;
        }

        public void Bark(int numTimes)
        {
            if (numTimes > 10)
                throw new ApplicationException("Too many times to bark");

            for (int i = 0; i < numTimes; i++)
                Console.WriteLine("Woof");
        }
    }

Catching an exception in ConsoleApplication1 that was thrown from DogLibrary:
915-002

#914 – Using the Debugger to Break when an Exception Is Thrown

By default, if you have an exception handler defined, the debugger in Visual Studio will not break (i.e. stop) at the point where an exception is thrown.

You can, however, configure Visual Studio to break at the point when the exception is thrown.  To enable breaking when an exception is thrown, do the following:

  • From the Debug menu, select Exceptions…

914-001

  • Find the specific type of exception for which you want the debugger to break and click on the Thrown column.  You can select an entire class of exceptions, or a specific exception type.  In the example below, we select all Common Language Runtime Exceptions.

914-002

  • Click the OK button

Now, when you run in debug mode, the debugger will display a dialog at the point where an exception is thrown and give you a chance to break (stop).

914-003

 

If you do break, you can then examine the exception object.

914-004