how to catch out of memory exception in c++?
can anyone please tell me how to catch out of memory exception?
for ex.
try
{
while(true)
{
int i = new int;
}
}
catch( ? <--- what should be put here?)
{
//exception handling
}
and also this,
queue<int> q;
try
{
while(true)
{
q.push(10);
}
}
catch( ? <---- what should be put here?)
{
//error handling
}
Catch std::bad_alloc
.
You will also need a strategy for handling the errors, since many of the things you'd like to do will require memory (even if it's only to display an error to the user before shutting down). One strategy is to allocate a block of memory at startup, and delete
it in the exception handler before attempting to use more memory, so that there is some available to use.
As others have noted, what you want to catch is std::bad_alloc
. You can also use catch(...)
or catch(exception& ex)
to catch any exception; the latter allows the exception data to be read and used in the exception handler.
Mark Ransom had already pointed out that when the program cannot allocate any more memory, even printing an error message may fail. Consider the following program:
#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
}
(I strongly recommend that the program be compiled as 32-bit to avoid running the system out of memory on a 64-bit machine. 32-bit programs cannot allocate more than 4 GB of memory, or 2 GB by default on Windows.)
When the first bad_alloc
gets thrown in the infinite while
loop, control is passed to the catch
block, but the program still fails with an unhandled exception. Why? Another bad_alloc
is thrown inside the exception handler while trying to print to cerr
. You can verify this by using a debugger: Set a breakpoint at the catch(bad_alloc& ex)
line, run the program in the debugger, then step through each statement once you reach the breakpoint. A bad_alloc
exception will be thrown in the cerr
statement.
As such, to properly handle an out-of-memory scenario, you need to set aside some memory so that you can print an error message before exiting. Otherwise, the program will just crash on an unhandled exception while trying to print the error message. To do so, you can allocate a block of memory that is deallocated in the exception handler, as Mark Ransom suggested:
// 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);
}
//...
catch (std::bad_alloc& ba){
cerr << "bad_alloc caught: " << ba.what() << endl;
}
As a note you should read bdonlan's comment. The call to cerr
may very well fail. Mark Ransom's suggestion in his answer is a good strategy to mitigate this issue.
You should catch
an object of type std::bad_alloc
.
Alternatively, you can also use a nothrow
verison of new
as:
int *pi = new (nothrow) int[N];
if(pi == NULL)
{
std::cout << "Could not allocate memory" << std::endl;
}
When you use this, no exception is thrown if the new
fails. Instead,it simply returns NULL
which you check before proceeding further.