Как уже отмечали другие, вы хотите поймать std::bad_alloc
. Вы также можете использовать catch(...)
или catch(exception& ex)
, чтобы поймать любое исключение; последний позволяет считывать данные об исключениях и использовать их в обработчике исключений.
Марк Рэнсом уже указывал, что, когда программа не может выделить больше памяти, даже печать сообщения об ошибке может завершиться неудачей. Рассмотрим следующую программу:
#include <iostream>
using namespace std;
int main() {
unsigned long long i = 0;
try {
while(true) {
// Leaks memory on each iteration as there is no matching delete
int* a = new int;
i++;
}
} catch(bad_alloc& ex) {
cerr << sizeof(int) * i << " bytes: Out of memory!";
cin.get();
exit(1);
}
return 0; // Unreachable
}
( Я настоятельно рекомендую скомпилировать программу как 32-разрядную, чтобы избежать нехватки памяти системы на 64-разрядной машине. 32-разрядные программы не могут выделять более 4 ГБ памяти или 2 ГБ по умолчанию в Windows. )
Когда первый bad_alloc
создается в бесконечном цикле while
, управление передается в блок catch
, но программа по-прежнему завершается ошибкой с необработанным исключением. Зачем? Другой bad_alloc
выбрасывается в обработчик исключений при попытке печати на cerr
. Вы можете проверить это с помощью отладчика: установите точку останова в строке catch(bad_alloc& ex)
, запустите программу в отладчике, а затем выполните каждый оператор, как только вы достигнете точки останова. Исключение bad_alloc
будет добавлено в оператор cerr
.
Таким образом, чтобы правильно обрабатывать сценарий нехватки памяти, вам необходимо выделить немного памяти, чтобы вы могли напечатать сообщение об ошибке перед выходом. В противном случае программа просто потерпит неудачу при необработанном исключении при попытке напечатать сообщение об ошибке. Для этого вы можете выделить блок памяти, который освобождается в обработчике исключений, как предложил Марк Рэнсом:
// Reserve 16K of memory that can be deleted just in case we run out of memory
char* _emergencyMemory = new char[16384];
// ...
try {
// ...
} catch(bad_alloc& ex) {
// Delete the reserved memory so we can print an error message before exiting
delete[] _emergencyMemory;
cerr << sizeof(int) * i << " bytes: Out of memory!";
cin.get();
exit(1);
}
//...