Managed Exception Handling using VC++.NET

Introduction

The managed extensions to C++ extends traditional C++ exception handling
capabilities and adds support for managed exception handling. This article does
not cover traditional exception handling or structured exception handling, and
is only meant as a guide to handling managed exceptions in an application that
makes use of the managed extensions to C++. Managed exceptions are simply
exceptions thrown by managed types (typically by classes in the BCL) and it's
recommended that you use the <code lang=mc++>System::Exception class as your exception object,
either directly or by creating your custom exception classes using this class as the base class.
While there is nothing preventing you from throwing managed objects that are not
derived from <code lang=mc++>System::Exception; one slight point to note is that you can only
throw <code lang=mc++>__gc objects, which basically means you cannot throw <code lang=mc++>__value objects
directly (but you can box them and throw the boxed object).

Note - In all the example code snippets, you'll see a <code lang=mc++>Show function
which is not really a function, but a preprocessor definition I added as follows
:-

#define Show Console::WriteLine

Throwing exceptions

Managed extensions are thrown using the <code lang=mc++>throw
statement.

In the above example I have thrown an exception of type <code lang=mc++>
System::Exception. <code lang=mc++>System::Exception is the
recommended base class for all managed exception classes and the .NET BCL
classes exclusively use this class or one of several derived classes for their
exception handling requirements. The output of calling the above function would
be something very similar to :-

in ThrowFunction
Unhandled Exception: System.Exception: asdf
at ThrowFunction() in c:\...\exceptionsdemo.cpp:line 23
at main() in c:\...\exceptionsdemo.cpp:line 138

Since we haven't handled the exception the CLR has handled it for us and it
displays the exception text message that we passed through the constructor
overload that we used to create the exception. Essentially the <code lang=mc++>
Exception constructor
that accepts a <code lang=mc++>
System::String just saves the passed string to a member variable called <code lang=mc++>
_message and this is then exposed through a read-only property called <code lang=mc++>
Message. In addition the CLR also prints out a stack trace by using the <code lang=mc++>
StackTrace property of the <code lang=mc++>
Exception class. So we can imagine that the CLR puts a catch-all
exception handler for all IL executables that run under it, and for caught
exceptions it just prints the text in the <code lang=mc++>
Message and <code lang=mc++>
StackTrace properties of the <code lang=mc++>
Exception object that was thrown. Of course this is an over-simplistic
projection of the CLR's activities, and the actual CLR processes might be
extensively more complicated than this humble visualization.

Handling exceptions

We handle exceptions by using <code lang=mc++>try-<code lang=mc++>catch
blocks.

What happens is that the code inside the <code lang=mc++>try block
gets executed till an exception occurs or the end of the <code lang=mc++>try
block is reached, and if an exception occurs then control jumps to the <code lang=mc++>
catch block. Any code remaining in the <code lang=mc++>try block
will not get executed as is obvious from the output of the above code snippet.
The <code lang=mc++>ThrowFunction function is the same as in the earlier
code snippet and we display the exception message using the <code lang=mc++>
Message property of the <code lang=mc++>System::Exception class.

One issue that might creep up with the above scenario is when you need to perform clean-up
operations. Let's say you have opened a disk file and while you are writing to
the disk-file an exception is raised, which means control has jumped to the
<code lang=mc++>catch block. Now the code that closes the disk-file does not get executed. A
rather inelegant solution is to close the file outside the <code lang=mc++>try-<code lang=mc++>catch block :-

if( file_is_open )
{
//close file
}

Now this might seem okay at first glance, but assume that you have nested
try-catch blocks (which is
quite normal when you write some proper code), now you'll need to be careful
where exactly you free your resources and you might also have to increase the
scope of temporary resource handle variables to allow them to be accessed
outside the try-catch blocks.
The solution to this issue is the __finally keyword
used to create __finally blocks which get executed
irrespective of whether or not an exception has been raised.

Now try running the above code, as such, once, and then run it again after
commenting out the call to the ThrowFunction function
in the try block. You'll see that in both cases
the code inside the __finally block does get executed.

Rethrowing exceptions

When you catch an exception inside a try-catch block there is a small issue -
any try-catch block that is higher up in the try-catch nested hierarchy will not
see this exception. Luckily it's quite easy to rethrow an exception.

and have overridden two of the overloaded constructors
of the base class. And in my catch blocks I now specify

MyException

as the type of exception object that is to be caught.

Multiple catch blocks

It's possible to have multiple

catch

blocks in any

try

-catch-__finally
block of code, which we can take advantage to specifically handle multiple
exception types that get thrown. Let's write a function that throws different
types of exceptions based on a parameter we pass to it :-

Remember to put the catch blocks in reverse order of
inheritance hierarchy, as otherwise the upper-classes in the inheritance chain
will get swallowed up by the lowest class in the hierarchy or any classes lower
than itself in the inheritance chain. For example, in the above code
snippet, had we put the Exception

catch

block above the MyException

catch

block it would then catch both Exception
type exceptions and MyException type exceptions, which
would be wholly undesirable, because the specific MyException

catch

block never gets executed.

You'll find quite frequently that several of the derived exception classes in
the .NET Base Class Library do not add any functionality to the

System::Exception

class. This is because these derived classes serve only
to isolate specific exceptions rather than actually add any extra methods or
properties to the Exception class. Let's assume that we are
going to open a file and then write some information into it. Now assuming that
exception scenarios might arise either when opening a file or when writing to
the opened file, we would obviously need to handle them differently, as in the
slightly contrived code snippet below.

__try_cast and System::InvalidCastException

While this is not directly pertaining to a general discussion on managed
exceptions, I thought I'd mention __try_cast here which
is an additional keyword supported by the managed extensions to C++. The casting
operator works exactly like the dynamic_cast operator
except that if the cast fails it throws a

Conclusion

I hope this article has thrown light on managed exception handling in
VC++.NET for programmers from a native C++ background, who are gradually moving
to .NET and Managed C++. For further information about .NET exception handling I
recommend Tom Archer's and Andrew Whitechapel's
Inside C# (2nd edition)[^] - specifically Chapter 12 (Pages 411 -
448).

History

August 09th 2003 - First published

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Nish Nishant is a Principal Software Architect based out of Columbus, Ohio. He has over 17 years of software industry experience in various roles including Lead Software Architect, Principal Software Engineer, and Product Manager. Nish was a Microsoft Visual C++ MVP between 2002 and 2015.

Nish is an industry acknowledged expert in the Microsoft technology stack. He authored C++/CLI in Action for Manning Publications in 2005, and had previously co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his WordPress blog. Nish is vastly experienced in team management, mentoring teams, and directing all stages of software development.

Contact Nish : If you are interested in hiring Nish as a consultant, you can reach him via his google email id voidnish.