如果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¤t=bad_alloc.jpg
答案 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