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 memperbolehkan penanganan 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 throw C++ diperluas untuk melempar handle ke tipe 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 native:

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

Keluaran

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 menelusuri tumpukan untuk mencari klausul tangkapan yang tepat, atau dalam kasus SEH, penyaring kecuali untuk SEH, agar bisa menangkap pengecualian. Klausa catch pertama-tama dicari dalam urutan leksikal, lalu secara dinamis ke bawah tumpukan panggilan.

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

  3. Setelah tumpukan dilepas, klausul tangkapan dijalankan.

Menangkap Jenis Tidak Terkelola

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

  • Jika jenis C++ asli ditemui, pengecualian diuraikan dan dibandingkan dengan jenis yang ditemui. Perbandingan ini memungkinkan jenis C++ asli ditangani dengan cara yang biasa.

  • 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 tipe bawaan C++ terlebih dahulu sebelum ada klausa tangkapan tipe CLR.

Perhatikan bahwa

catch(Object^)

dan

catch(...)

keduanya akan menangkap jenis yang dilemparkan termasuk pengecualian SEH.

Jika tipe yang tidak terkelola ditangkap oleh catch(Object^), objek yang dilemparkan tidak akan dihancurkan.

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

Lihat juga

Penanganan Pengecualian
safe_cast
Penanganan Pengecualian