std :: bad_alloc没有被任何调用堆栈帧捕获

时间:2011-07-27 09:39:55

标签: c++ try-catch bad-alloc

如果new运算符无法分配内存,则只有在我立即围绕新语句放置try-catch块时才会捕获异常std :: bad_alloc。如果我在调用者中有一些try-catch块在下面的几个堆栈帧中,那么它就不会被捕到并且我得到一个异常的程序终止。为什么会这样?这是在Microsoft Visual Studio 2008上。

编辑:好的,这是不起作用的代码。下面的函数是我调用new的地方,下面的是下面的堆栈帧。最后一个函数是我有catch子句但它没有被捕到的地方。

void HTTPResponseBuff::grow()
{
    if (m_nMaxSize > m_nStartConstGrowSize)
        m_nMaxSize += m_nConstGrowSize;
    else
        m_nMaxSize = 2 * m_nMaxSize;

    char* pTmp = new char[m_nMaxSize];
    . . . 
}

void HTTPResponseBuff::write(const char* pBuf, size_t len)
{
    char* pCh;
    while (getRemainingCapacity(pCh) < len)
        grow();
    . . . 
}

size_t HTTPTransport::responseCallback(void *pRespData, size_t size,
                             size_t nmemb, void *pRespBuff)
{
    const char* pChar = (const char*)pRespData;
    register int respDataLen = size * nmemb;    
    ((HTTPResponseBuff*)pRespBuff)->write(pChar, respDataLen);
    return respDataLen;
}

A few curl library stackframes here. These are C code, not C++.

ISTATUS HTTPTransport::invoke()
{
    invokeCleanup();

    //make the HTTP call
    CURLcode retCode;
    try{
    retCode = curl_easy_perform(m_pCurl);
    }
    catch(std::bad_alloc& ba)
    {
        strcpy(m_pErrMsg,ba.what());
        m_status = IFAILURE;
    }
}

当我捕获bad_alloc时(在紧跟新语句的catch子句中)的堆栈帧也在这里:http://s289.photobucket.com/albums/ll211/spiderman2_photo_bucket/?action=view&current=bad_alloc.jpg

2 个答案:

答案 0 :(得分:2)

您在异常来源和try-catch之间提到了第三方函数。 如果这些第三方函数不是c ++(例如具有c链接,就像用c语言编写的libcurl那样)那么异常处理将无法按预期工作。我对使用gcc的项目有同样的问题。

您需要捕获回调中的所有异常,然后才能通过第三方层传播并使用错误代码(或自定义机制)将信息传入您的调用方或完全放弃使用异常。


当你问我做了什么:我有一个来自调用者的上下文对象通过可用的void指针注入回调。所以我将上下文对象更改为具有ErrorStatus和ErrorMessage成员,并使用它们通过C层传播错误。

struct Context{
    ErrorCode errorCode;
    const char* errorMessage;
    //other stuff
}

void callback(T arg, void* context){
   try{
      new(int);
   }catch(std::exception &e){
       context.errorCode=getErrorCode(e);
       context.errorMessage=e.what();
   }

}

void caller(){
    Context context;
    thirdparty_function(context);

}

如果你不担心线程安全,你也可以使用全局变量。

也就是说,以这种方式处理内存不足可能会很棘手,因为你应该避免为错误消息分配额外的内存

答案 1 :(得分:0)

如果可能,发布你的代码,没有你的代码我写了一个小测试,try / catch似乎工作得很好,即使有更多的堆栈框架(这个例子适用于gcc):

void foo()
{
    int* myarray= new int[1000000000];
}

void foo1()
{
     int i = 9;
     foo();
}

void foo2()
{
     int j = 9;
     foo1();
}

int main () {
  try
  {
         foo2();
  }
  catch (exception& e)
  {
    cout << "Standard exception: " << e.what() << endl;
  }
  system("pause");
  return 0;
}

输出

  

标准例外:St9bad_alloc