在使用托管异常的基本概念
本主题介绍托管应用程序讨论异常处理。 即生成与 /clr 编译器选项的应用程序。
主题内容
在 /clr 下的引发的异常。
try/catch 为 CLR 扩展块
备注
如果使用编译 /clr 选项,您可以处理 CLR 异常以及标准 C++ 异常处理 和 结构化异常处理 (她)。 CLR 异常是托管类型引发的所有异常。 System::Exception 类为进程中的 CLR 异常提供了许多有用的方法和建议用作用户定义的异常类的基类。
从接口派生的捕获异常类型不支持在 /clr下。 此外,公共语言运行时不允许您捕捉堆栈溢出异常;堆栈溢出异常将终止进程。
有关异常处理的差异的更多信息在托管和非托管应用程序,请参见 在异常处理行为差异在 C++ 托管扩展中。
在 /clr 下的引发的异常。
C++ 引发表达式扩展引发句柄 CLR 类型。 下面的示例创建一个自定义异常类型然后引发该类型的实例:
// clr_exception_handling.cpp
// compile with: /clr /c
ref struct MyStruct: public System::Exception {
public:
int i;
};
void GlobalFunction() {
MyStruct^ pMyStruct = gcnew MyStruct;
throw pMyStruct;
}
必须在引发之前装箱值类型:
// clr_exception_handling_2.cpp
// compile with: /clr /c
value struct MyValueStruct {
int i;
};
void GlobalFunction() {
MyValueStruct v = {11};
throw (MyValueStruct ^)v;
}
try/catch 为 CLR 扩展块
同样 try/catch 块结构可用于捕获 CLR 和本机异常使用:
// clr_exception_handling_3.cpp
// compile with: /clr
using namespace System;
ref struct MyStruct : public Exception {
public:
int i;
};
struct CMyClass {
public:
double d;
};
void GlobalFunction() {
MyStruct^ pMyStruct = gcnew MyStruct;
pMyStruct->i = 11;
throw pMyStruct;
}
void GlobalFunction2() {
CMyClass c = {2.0};
throw c;
}
int main() {
for ( int i = 1; i >= 0; --i ) {
try {
if ( i == 1 )
GlobalFunction2();
if ( i == 0 )
GlobalFunction();
}
catch ( CMyClass& catchC ) {
Console::WriteLine( "In 'catch(CMyClass& catchC)'" );
Console::WriteLine( catchC.d );
}
catch ( MyStruct^ catchException ) {
Console::WriteLine( "In 'catch(MyStruct^ catchException)'" );
Console::WriteLine( catchException->i );
}
}
}
Output
In 'catch(CMyClass& catchC)'
2
In 'catch(MyStruct^ catchException)'
11
展开 C++ 对象的顺序
展开用于可以在该引发的功能和该托管函数之间的运行时堆栈的析构函数的所有 C++ 对象发生。 由于 CLR 类型在堆中分配,展开不适用于它们。
事件顺序引发的异常的如下:
运行时遍历查找正确 catch 子句的堆栈,但如果这样,但她的筛选器,捕获异常。 catch 子句中搜索动态首先按词法顺序,然后在调用堆栈下。
对于查找正确的处理程序,将展开堆栈到该点。 对于每个函数调用堆栈,其本地对象析构和 __finally 块从嵌套执行,向外。
一旦将展开堆栈, catch 子句执行。
捕获非托管类型
当非托管对象类型时,它将具有类型 System::Runtime.InteropServices::SEHException的异常。 在搜索适当的 catch 子句时,有两种可能性。
如果本机 C++ 类型遇到异常,将展开并将遇到的类型进行比较。 此比较允许本机 C++ 类型捕获以常规方法。
但是,因此,如果 catch 子句其基类的类型 SEHException 或任何首先检查,子句将截获异常。 因此,因此应将首先在 CLR 类型之前所有 catch 子句捕获本机 C++ 类型的所有 catch 子句。
请注意
catch(Object^)
和
catch(...)
两个将捕捉任何时引发的类型包括 SEH 异常。
如果非托管类型由缓存 (System::object^) 捕获,它不会销毁引发的对象。
当引发的或捕捉中未经处理的异常,建议您使用 /EHsc 编译器选项而不是 /EHs 或 /EHa。