Pengecualian: Membebaskan Objek dalam Pengecualian
Artikel ini menjelaskan kebutuhan dan metode membebaskan objek ketika pengecualian terjadi. Topik meliputi:
Pengecualian yang dilemparkan oleh kerangka kerja atau oleh aplikasi Anda mengganggu alur program normal. Dengan demikian, sangat penting untuk melacak objek dengan cermat sehingga Anda dapat membuangnya dengan benar jika pengecualian dilemparkan.
Ada dua metode utama untuk melakukan ini.
Tangani pengecualian secara lokal menggunakan
try
kata kunci dancatch
, lalu hancurkan semua objek dengan satu pernyataan.Hancurkan objek apa pun di
catch
blok sebelum melempar pengecualian di luar blok untuk penanganan lebih lanjut.
Kedua pendekatan ini diilustrasikan di bawah ini sebagai solusi untuk contoh bermasalah berikut:
void SomeFunc() // Problematic code
{
CPerson* myPerson = new CPerson;
// Do something that might throw an exception.
myPerson->SomeFunc();
// Now destroy the object before exiting.
// If SomeFunc above throws an exception this code will
// not be reached and myPerson will not be deleted.
delete myPerson;
}
Seperti yang ditulis di atas, myPerson
tidak akan dihapus jika pengecualian dilemparkan oleh SomeFunc
. Eksekusi melompat langsung ke handler pengecualian luar berikutnya, melewati keluar fungsi normal dan kode yang menghapus objek. Penunjuk ke objek keluar dari cakupan ketika pengecualian meninggalkan fungsi, dan memori yang ditempati oleh objek tidak akan pernah dipulihkan selama program berjalan. Ini adalah kebocoran memori; itu akan terdeteksi dengan menggunakan diagnostik memori.
Menangani Pengecualian Secara Lokal
Paradigma try/catch menyediakan metode pemrograman defensif untuk menghindari kebocoran memori dan memastikan bahwa objek Anda dihancurkan ketika pengecualian terjadi. Misalnya, contoh yang ditunjukkan sebelumnya dalam artikel ini dapat ditulis ulang sebagai berikut:
void SomeFunc()
{
CPerson* myPerson = new CPerson;
try
{
// Do something that might throw an exception.
myPerson->SomeFunc();
}
catch (CException* e)
{
// Handle the exception locally
e->Delete();
}
// Now destroy the object before exiting.
delete myPerson;
}
Contoh baru ini menyiapkan handler pengecualian untuk menangkap pengecualian dan menanganinya secara lokal. Kemudian keluar dari fungsi secara normal dan menghancurkan objek. Aspek penting dari contoh ini adalah bahwa konteks untuk menangkap pengecualian ditetapkan dengan blok coba/tangkap . Tanpa bingkai pengecualian lokal, fungsi tidak akan pernah tahu bahwa pengecualian telah dilemparkan dan tidak akan memiliki kesempatan untuk keluar secara normal dan menghancurkan objek.
Melemparkan Pengecualian Setelah Menghancurkan Objek
Cara lain untuk menangani pengecualian adalah dengan meneruskannya ke konteks penanganan pengecualian luar berikutnya. Di blok Anda catch
, Anda dapat melakukan pembersihan objek yang dialokasikan secara lokal dan kemudian memberikan pengecualian untuk pemrosesan lebih lanjut.
Fungsi pelemparan mungkin atau mungkin tidak perlu membatalkan alokasi objek tumpukan. Jika fungsi selalu membatalkan alokasi objek timbunan sebelum kembali dalam kasus normal, maka fungsi juga harus membatalkan alokasi objek timbunan sebelum melemparkan pengecualian. Di sisi lain, jika fungsi biasanya tidak membatalkan alokasi objek sebelum kembali dalam kasus normal, maka Anda harus memutuskan berdasarkan kasus per kasus apakah objek timbunan harus dibatalkan alokasinya.
Contoh berikut menunjukkan bagaimana objek yang dialokasikan secara lokal dapat dibersihkan:
void SomeFunc()
{
CPerson* myPerson = new CPerson;
try
{
// Do something that might throw an exception.
myPerson->SomeFunc();
}
catch (CException* e)
{
e->ReportError();
// Destroy the object before passing exception on.
delete myPerson;
// Throw the exception to the next handler.
throw;
}
// On normal exits, destroy the object.
delete myPerson;
}
Mekanisme pengecualian secara otomatis membatalkan alokasi objek bingkai; destruktor objek bingkai juga dipanggil.
Jika Anda memanggil fungsi yang dapat melemparkan pengecualian, Anda dapat menggunakan blok try/catch untuk memastikan bahwa Anda menangkap pengecualian dan memiliki kesempatan untuk menghancurkan objek apa pun yang telah Anda buat. Secara khusus, ketahuilah bahwa banyak fungsi MFC dapat melemparkan pengecualian.
Untuk informasi selengkapnya, lihat Pengecualian: Menangkap dan Menghapus Pengecualian.