共用方式為


在使用基本的概念管理例外狀況

本主題討論 managed 應用程式中處理的例外狀況。 也就是以編譯的應用程式**/clr**編譯器選項。

本主題內容

  • 擲回例外狀況下 /clr

  • Try/Catch 區塊的 CLR 擴充

備註

如果使用編譯**/clr**選項,您可以處理 CLR 例外狀況,以及標準 C++ 例外處理結構化的例外處理 (SEH)。 CLR 例外狀況是由 managed 型別所擲回任何例外狀況。 System::Exception 類別提供許多有用的方法,以處理 CLR 例外狀況,並建議您為使用者定義的例外狀況的基底類別。

攔截例外狀況型別衍生自介面不支援**/clr**。 此外,common language runtime 不允許您以攔截堆疊溢位例外狀況。 堆疊溢位例外狀況將會終止處理程序。

如需有關在 managed 和 unmanaged 應用程式中的例外處理的差異的詳細資訊,請參閱差異例外狀況處理行為在 Managed Extensions for C++

擲回例外狀況下 /clr

C + + 的 throw 運算式會擲回一個控點,到 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;
}

必須先擲 boxed 實值型別:

// 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 擴充

相同/攔截區塊結構可用來攔截 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 );
      }
   }
}

df24ysb6.collapse_all(zh-tw,VS.110).gifOutput

In 'catch(CMyClass& catchC)'
2
In 'catch(MyStruct^ catchException)'
11

df24ysb6.collapse_all(zh-tw,VS.110).gifC + + 物件的復原順序

回溯,就會發生的任何具有解構函式的作品,執行階段之間的堆疊上擲回的函式,並處理函式的 C++ 物件。 因為 CLR 型別在堆積上配置,回溯不適用於它們。

擲回的例外狀況的事件順序如下所示:

  1. 執行階段查核會查詢適當的 catch 子句,或者如果是 SEH,堆疊除了 SEH,攔截例外狀況篩選條件。 Catch 子句會先搜尋語彙的順序,並以動態方式循列呼叫堆疊。

  2. 一旦找到正確的處理常式時,堆疊會回溯至該點。 每個函式呼叫堆疊上,其區域物件的解構和 __finally 區塊執行,大部分從巢狀游標向外拖拉。

  3. 當堆疊回溯之後,便會執行 catch 子句。

df24ysb6.collapse_all(zh-tw,VS.110).gif攔截未受管理的型別

擲回的未受管理的物件型別時,它會包裝的例外狀況型別的 System::Runtime.InteropServices::SEHException。 當搜尋適當的攔截子句中,有兩個可能的情況。

  • 如果原生的 C++ 型別,會解除包裝例外狀況,而且相較於發生的型別。 這項比較讓以一般方式攔截的原生 C++ 型別。

  • 不過,如果攔截 的型別子句 SEHException 或任何其基底類別會先檢查,則子句會攔截的例外狀況。 因此,您應該將所有的 catch 子句任何 catch 子句的 CLR 型別之前,先攔截原生 C++ 型別。

請注意

catch(Object^)

catch(...)

兩者會攔截任何擲回的型別,包括 SEH 例外狀況。

如果未受管理的型別被 catch(Object^),它不會損壞擲回的物件。

當擲回,或攔截不受管理的例外狀況時,我們建議您採用 /EHsc 編譯器選項,而不是**/EHs/EHa**。

請參閱

參考

safe_cast (C++ 元件擴充功能)

在 Visual C++ 中處理的例外狀況

其他資源

例外狀況處理 (C++ 元件擴充功能)