如何在c ++中捕获内存不足?

时间:2011-10-13 03:15:34

标签: c++ exception try-catch

任何人都可以告诉我如何捕获内存异常吗?

代表

try
{
    while(true)
    {
        int i = new int;
    }
}
catch( ? <--- what should be put here?)
{
    //exception handling
}

还有这个,

queue<int> q;
try
{
     while(true)
     {
          q.push(10);
     }
}
catch( ? <---- what should be put here?)
{
     //error handling
}

4 个答案:

答案 0 :(得分:48)

抓住std::bad_alloc

您还需要一个处理错误的策略,因为您要做的许多事情都需要内存(即使它只是在关闭之前向用户显示错误)。一种策略是在启动时分配一块内存,并在尝试使用更多内存之前在异常处理程序delete,以便有一些可用。

答案 1 :(得分:18)

正如其他人所说,你想要捕捉的是std::bad_alloc。您还可以使用catch(...)catch(exception& ex)来捕获任何异常;后者允许在异常处理程序中读取和使用异常数据。

Mark Ransom已经指出,当程序无法分配更多内存时,即使打印错误信息也可能失败。请考虑以下程序:

#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 GB的内存,或2 GB默认情况下在Windows上。

当第一个bad_alloc被抛入无限while循环时,控制权被传递给catch块,但程序仍会因未处理的异常而失败。为什么?在尝试打印到bad_alloc时,另一个cerr在异常处理程序中被抛出。您可以使用调试器对此进行验证:在catch(bad_alloc& ex)行设置断点,在调试器中运行程序,然后在到达断点后逐步执行每个语句。 bad_alloc语句中会抛出cerr个异常。

因此,要正确处理内存不足的情况,您需要预留一些内存,以便在退出之前打印错误消息。否则,程序将在尝试打印错误消息时在未处理的异常上崩溃。为此,您可以分配在异常处理程序中释放的内存块,正如Mark Ransom所建议的那样:

// 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);
}
//...

答案 2 :(得分:14)

catch (std::bad_alloc& ba){
    cerr << "bad_alloc caught: " << ba.what() << endl;
}

作为一个注释你应该阅读bdonlan的评论。对cerr的调用很可能会失败。 Mark Ransom在他的回答中提出了一个缓解这个问题的好策略。

答案 3 :(得分:5)

您应该catch std::bad_alloc类型的对象。

或者,您也可以使用nothrow new的{​​{1}}版本:

int *pi = new (nothrow) int[N]; 
if(pi == NULL) 
{
   std::cout << "Could not allocate memory" << std::endl;
}

使用此功能时,如果new失败,则不会引发异常。相反,它只返回您检查的NULL,然后再继续。