how to catch out of memory exception in c++?

后端 未结 4 1463
耶瑟儿~
耶瑟儿~ 2020-12-04 16:46

can anyone please tell me how to catch out of memory exception?

for ex.

try
{
    while(true)
    {
        int i = new int;
    }
}
catch( ? <---         


        
相关标签:
4条回答
  • 2020-12-04 17:05

    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);
    }
    //...
    
    0 讨论(0)
  • 2020-12-04 17:12

    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.

    0 讨论(0)
  • 2020-12-04 17:16

    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.

    0 讨论(0)
  • 2020-12-04 17:16
    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.

    0 讨论(0)
提交回复
热议问题