Bagikan melalui


Konsep Dasar dalam Menggunakan Pengecualian Terkelola

Topik ini membahas penanganan pengecualian dalam aplikasi terkelola. Artinya, aplikasi yang dikompilasi dengan opsi /clr compiler.

Dalam topik ini

Keterangan

Jika Anda mengkompilasi dengan opsi /clr , Anda dapat menangani pengecualian CLR serta kelas standar Exception menyediakan banyak metode yang berguna untuk memproses pengecualian CLR dan direkomendasikan sebagai kelas dasar untuk kelas pengecualian yang ditentukan pengguna.

Menangkap jenis pengecualian yang berasal dari antarmuka tidak didukung di bawah /clr. Selain itu, runtime bahasa umum tidak mengizinkan Anda untuk menangkap pengecualian luapan tumpukan; pengecualian luapan tumpukan akan mengakhiri proses.

Untuk informasi selengkapnya tentang perbedaan penanganan pengecualian dalam aplikasi terkelola dan tidak terkelola, lihat Perbedaan perilaku penanganan pengecualian di bawah Ekstensi Terkelola untuk C++.

Melempar pengecualian di bawah /clr

Ekspresi pelemparan C++ diperluas untuk melemparkan handel ke jenis CLR. Contoh berikut membuat jenis pengecualian kustom lalu melempar instans jenis tersebut:

// 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;
}

Jenis nilai harus dikotak sebelum dilemparkan:

// clr_exception_handling_2.cpp
// compile with: /clr /c
value struct MyValueStruct {
   int i;
};

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

Coba/Tangkap Blok untuk Ekstensi CLR

Struktur blok yang sama try/catch dapat digunakan untuk menangkap pengecualian CLR dan asli:

// 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 );
      }
   }
}

Hasil

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

Urutan Unwinding untuk Objek C++

Unwinding terjadi untuk objek C++ apa pun dengan destruktor yang mungkin berada di tumpukan run-time antara fungsi pelemparan dan fungsi penanganan. Karena jenis CLR dialokasikan pada tumpukan, unwinding tidak berlaku untuk mereka.

Urutan peristiwa untuk pengecualian yang dilemparkan adalah sebagai berikut:

  1. Runtime berjalan tumpukan mencari klausul tangkapan yang sesuai, atau dalam kasus SEH, kecuali filter untuk SEH, untuk menangkap pengecualian. Klausa catch dicari terlebih dahulu dalam urutan leksikal, dan kemudian secara dinamis menurunkan tumpukan panggilan.

  2. Setelah handler yang benar ditemukan, tumpukan dilepaskan ke titik tersebut. Untuk setiap panggilan fungsi pada tumpukan, objek lokalnya dihancurkan dan __finally blok dijalankan, dari sebagian besar bersarang ke luar.

  3. Setelah tumpukan dilepas, klausul tangkapan dijalankan.

Menangkap Jenis Tidak Terkelola

Ketika jenis objek yang tidak dikelola dilemparkan, itu dibungkus dengan pengecualian jenis SEHException. Saat mencari klausul yang sesuai catch , ada dua kemungkinan.

  • Jika jenis C++ asli ditemui, pengecualian dibongkar dan dibandingkan dengan jenis yang ditemui. Perbandingan ini memungkinkan jenis C++ asli tertangkap dengan cara normal.

  • Namun, jika catch klausul jenis SEHException atau salah satu kelas dasarnya diperiksa terlebih dahulu, klausul akan mencegat pengecualian. Oleh karena itu, Anda harus menempatkan semua klausa tangkapan yang menangkap jenis C++ asli terlebih dahulu sebelum ada klausa tangkapan jenis CLR.

Perhatikan bahwa

catch(Object^)

dan

catch(...)

keduanya akan menangkap jenis yang dilemparkan termasuk pengecualian SEH.

Jika jenis yang tidak dikelola ditangkap oleh catch(Object^), itu tidak akan menghancurkan objek yang dilemparkan.

Saat melempar atau menangkap pengecualian yang tidak dikelola, kami sarankan Anda menggunakan opsi kompilator /EHsc alih-alih /EH atau /EHa.

Baca juga

Penanganan Pengecualian
safe_cast
Penanganan Pengecualian