NGWS SDK Documentation  

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

Handling Exceptions Using Managed Extensions for C++

In addition to structured exception handling (SEH) and C++ exception handling, Managed Extensions for C++ extend this feature by supporting the handling of managed exceptions. A managed exception is any exception thrown by a managed type. The System::Exception class provides many useful methods for processing managed exceptions and is recommended as a base class for user-defined exception classes.

Throwing Exceptions Using Managed Extensions

The C++ throw expression is extended to throw a pointer to any managed object. The following example creates a custom exception type and then throws an instance of that type:

#using <mscorlib.dll>
__gc struct MyStruct : public System::Exception { int i; };

void GlobalFunction()
{
   MyStruct* pMyStruct = new MyStruct;
   throw pMyStruct;
}

Value classes must be boxed before they can be thrown:

#using <mscorlib.dll>
__value struct MyValueStruct { int i; };

void GlobalFunction()
{
   MyValueStruct v = {11};
   throw __box(v);
}

Try/Catch Blocks Using Managed Extensions

The same try/catch block structure can be used for catching both managed and unmanaged exceptions. The following example demonstrates a simple try/catch block with managed and unmanaged structures:

#using <mscorlib.dll>
__gc struct MyStruct : public System::Exception { int i; };
struct CMyClass { double d; };
void GlobalFunction()
{
   MyStruct * pMyStruct = new MyStruct;
   pMyStruct->i = 11;
   throw pMyStruct;
}
void GlobalFunction2()
{
   MyClass c = {2.0}; throw c;
}
void main()
{
   for(int i = 1; i >= 0; --i)
   {
    try
    {
     if( i==1) GlobalFunction2();
     if( i==0) GlobalFunction();
    }
    catch(CMyClass& catchC)
    {
     Console::WriteLine(catchC.d);
    }
    catch(MyStruct* catchException)
    {
     Console::WriteLine(catchException->i);
    }
   }
}

Program Output

2
11

Order of Unwinding for C++ Objects

As usual, unwinding occurs for any C++ objects with destructors that may be on the run-time stack between the throwing function and the handling function. Because garbage-collected classes are allocated on the heap, unwinding does not apply to them.

Catching Unmanaged C++ Types

When an unmanaged C++ object type is thrown, it is wrapped with a NGWS runtime exception of type System::Runtime::InteropServices::SEHException. When searching for the appropriate catch clause, there are two possibilities.

If an unmanaged C++ type is encountered, the exception is unwrapped and compared to the type encountered. This comparison allows an unmanaged C++ type to be caught in the normal way.

However, if a catch clause of type SEHException or any of its base classes is examined first, the clause will intercept the exception. Therefore, you should place all catch clauses that catch unmanaged C++ types first before any catch clauses of managed types.

Managed Extensions and the __finally Keyword

In addition to try and catch clauses, Managed Extensions support a __finally clause. The semantics are identical to the __finally block in structured exception handling (SEH). A __finally block may follow a try or catch block.

The purpose of the __finally block is to clean up any resources left after the exception occurred. Note that the __finally block is always executed, even if no exception was thrown. The catch block is only executed if a managed exception is thrown within the associated try block.

The following example demonstrates a simple __finally block:

#using <mscorlib.dll>
__gc class MyException : public System::Exception
{
};
void ThrowMyException()
{
   throw new MyException;
}

void main()
{
   try
   {
    ThrowMyException();
   }
   catch (MyException *e)
   {
    Console::WriteLine("in catch");
    Console::WriteLine(e->GetType());
   }
   __finally
   {
    Console::WriteLine("in finally");
   }
}

Program Output

in catch
MyException
in finally

See Also

Introduction to Managed Extensions for C++ | _try_cast | Exception Handling