Bagaimana untuk berurusan dengan bad_alloc di C++?
Ada sebuah metode yang disebut foo
yang kadang-kadang menghasilkan galat berikut:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Abort
Apakah ada cara bahwa saya dapat menggunakan coba-coba
-menangkap
blok untuk menghentikan kesalahan ini mengakhiri program saya (semua saya ingin lakukan adalah kembali -1
)?
Jika demikian, apa yang merupakan sintaks untuk itu?
Bagaimana lagi yang bisa saya berurusan dengan bad_alloc
di C++?
51
6
Secara umum anda tidak, dan tidak harus mencoba, untuk menanggapi kesalahan ini.
bad_alloc
menunjukkan bahwa sumber daya yang tidak dapat dialokasikan karena tidak tersedia cukup memori. Dalam kebanyakan skenario program anda tidak bisa berharap untuk mengatasi dengan itu, dan mengakhiri segera adalah satu-satunya yang berarti perilaku.Lebih buruk lagi, sistem operasi modern sering di-alokasikan: pada sistem seperti ini,
malloc
danbaru
dapat berlaku pointer bahkan jika tidak ada cukup memori yang tersisa –std::bad_alloc
tidak akan pernah dilempar, atau setidaknya bukan tanda yang dapat diandalkan dari memori kelelahan. Sebaliknya, upaya untuk akses memori yang dialokasikan maka akan mengakibatkan kesalahan segmentasi, yang tidak catchable (anda dapat handle segmentasi sinyal kesalahan, tetapi anda tidak dapat melanjutkan program sesudahnya).Satu-satunya hal yang anda bisa lakukan ketika catching
std::bad_alloc
adalah mungkin log kesalahan, dan mencoba untuk memastikan aman program penghentian dengan membebaskan sumber daya yang luar biasa (tapi ini dilakukan secara otomatis dalam kegiatan normal dari tumpukan unwinding setelah kesalahan akan dilemparkan jika program menggunakan RAII tepat).Dalam kasus-kasus tertentu program dapat mencoba untuk membebaskan beberapa memori dan coba lagi, atau menggunakan memori sekunder (= disk), bukan dari RAM tetapi peluang tersebut hanya ada dalam skenario yang sangat spesifik dengan kondisi yang ketat:
Ini sangat jarang bahwa aplikasi memiliki kontrol atas point 1 — login sistem aplikasi tidak pernah melakukan, itu adalah sistem pengaturan yang memerlukan izin root untuk mengubah.1
OK, jadi mari kita asumsikan anda sudah fixed point 1. Apa yang sekarang dapat anda lakukan adalah misalnya menggunakan LRU cache untuk beberapa data anda (mungkin beberapa sangat besar bisnis benda-benda yang dapat diregenerasi atau reloaded on demand). Selanjutnya, anda perlu untuk menempatkan sebenarnya logika yang mungkin gagal menjadi fungsi yang mendukung retry — dengan kata lain, jika itu akan dibatalkan, anda hanya dapat peluncuran ini:
`` lru_cache widget_cache;
double perform_operation(int widget_id) { std::opsional maybe_widget = widget_cache.find_by_id(widget_id); jika (tidak maybe_widget) { maybe_widget = widget_cache.toko(widget_id, load_widget_from_disk(widget_id)); } kembali maybe_widget->frobnicate(); }
...
for (int num_attempts = 0; num_attempts < MAX_NUM_ATTEMPTS; ++num_attempts) { try { kembali perform_operation(widget_id); } catch (std::bad_alloc const&) { jika (widget_cache.kosong()) throw; // error di tempat lain. widget_cache.remove_oldest(); } }
// Menangani terlalu banyak usaha yang gagal di sini. ``
Namun bahkan di sini, menggunakan
std::set_new_handler
bukan penangananstd::bad_alloc
memberikan manfaat yang sama dan akan menjadi jauh lebih sederhana.1 Jika anda membuat sebuah aplikasi yang tidak control point 1, dan anda sedang membaca jawaban ini, silahkan menembak saya email, saya benar-benar ingin tahu tentang keadaan anda.
Apa itu C++ Standar yang ditentukan perilaku
baru
di c++?Gagasan biasa adalah bahwa jika
baru
operator tidak dapat mengalokasikan memori dinamis dari ukuran yang diminta, maka harus melempar pengecualian dari jenisstd::bad_alloc
. Namun, sesuatu terjadi bahkan sebelumbad_alloc
pengecualian dilemparkan:C++03 Bagian 3.7.4.1.3: kata
Perhatikan contoh kode berikut:
Anda dapat menangkap hal itu seperti yang lain kecuali:
Cukup apa yang anda dapat berguna lakukan dari titik ini adalah terserah anda, tapi itu's pasti layak secara teknis.
Saya tidak akan menyarankan hal ini, karena
bad_alloc
berarti anda memori. Itu akan menjadi yang terbaik untuk menyerah, bukannya mencoba untuk pulih. Namun berikut ini adalah solusi yang anda minta:Boleh saya sarankan lebih sederhana (dan lebih cepat) solusi untuk ini.
baru
operator akan mengembalikan null jika memori tidak dapat dialokasikan.Saya berharap ini bisa membantu!
Biarkan anda foo program exit dengan cara yang terkontrol:
Kemudian menulis program shell yang memanggil program yang sebenarnya. Karena ruang alamat yang terpisah, keadaan program shell selalu didefinisikan dengan baik.