Bagikan melalui


Pengecualian: Perubahan Makro Pengecualian di Versi 3.0

Ini adalah topik lanjutan.

Di MFC versi 3.0 dan yang lebih baru, makro penanganan pengecualian telah diubah untuk menggunakan pengecualian C++. Artikel ini menjelaskan bagaimana perubahan tersebut dapat memengaruhi perilaku kode yang ada yang menggunakan makro.

Artikel ini membahas topik berikut ini:

Jenis Pengecualian dan Makro CATCH

Dalam versi MFC sebelumnya, makro CATCH menggunakan informasi jenis run-time MFC untuk menentukan jenis pengecualian; jenis pengecualian ditentukan, dengan kata lain, di situs tangkapan. Namun, dengan pengecualian C++, jenis pengecualian selalu ditentukan di situs lemparan berdasarkan jenis objek pengecualian yang dilemparkan. Ini akan menyebabkan ketidaksesuaian dalam kasus yang jarang terjadi di mana jenis penunjuk ke objek yang dilemparkan berbeda dari jenis objek yang dilemparkan.

Contoh berikut mengilustrasikan konsekuensi dari perbedaan ini antara MFC versi 3.0 dan versi yang lebih lama:

TRY
{
   THROW((CException*) new CCustomException());
}
CATCH(CCustomException, e)
{
   TRACE("MFC 2.x will land here\n");
}
AND_CATCH(CException, e)
{
   TRACE("MFC 3.0 will land here\n");
}
END_CATCH

Kode ini berperilaku berbeda dalam versi 3.0 karena kontrol selalu meneruskan ke blok pertama catch dengan deklarasi pengecualian yang cocok. Hasil ekspresi lemparan

THROW((CException*) new CCustomException());

dilemparkan sebagai CException*, meskipun dibangun sebagai CCustomException. Makro CATCH di MFC versi 2.5 dan yang lebih lama menggunakan CObject::IsKindOf untuk menguji jenis pada waktu proses. Karena ekspresi

e->IsKindOf(RUNTIME_CLASS(CException));

benar, blok tangkapan pertama menangkap pengecualian. Dalam versi 3.0, yang menggunakan pengecualian C++ untuk mengimplementasikan banyak makro penanganan pengecualian, blok tangkapan kedua cocok dengan yang dilemparkan CException.

Kode seperti ini jarang. Biasanya muncul ketika objek pengecualian diteruskan ke fungsi lain yang menerima generik CException*, melakukan pemrosesan "pra-lemparan", dan akhirnya melemparkan pengecualian.

Untuk mengatasi masalah ini, pindahkan ekspresi lemparan dari fungsi ke kode panggilan dan berikan pengecualian dari jenis aktual yang diketahui pengkompilasi pada saat pengecualian dibuat.

Kembali Melemparkan Pengecualian

Blok tangkapan tidak dapat melemparkan pointer pengecualian yang sama yang tertangkap.

Misalnya, kode ini valid di versi sebelumnya, tetapi akan memiliki hasil yang tidak terduga dengan versi 3.0:

TRY
{
   // Do something to throw an exception.
   AfxThrowUserException();
}
CATCH(CException, e)
{
   THROW(e);    // Wrong. Use THROW_LAST() instead
}
END_CATCH
   }

Menggunakan THROW di blok tangkapan menyebabkan pointer e dihapus, sehingga situs tangkapan luar akan menerima pointer yang tidak valid. Gunakan THROW_LAST untuk melemparkan ekembali .

Untuk informasi selengkapnya, lihat Pengecualian: Menangkap dan Menghapus Pengecualian.

Baca juga

Penanganan Pengecualian