C++ std::bad_alloc没有在任何调用堆栈帧中被捕获
如果新操作符无法分配内存,只有在新语句周围立即放置try-catch块时,才会捕获异常std::bad_alloc。如果我在下面几帧的调用程序中使用try-catch块,它就不会在那里被捕获,我会得到一个异常的程序术语。为什么会发生这种情况?这是在MicrosoftVisualStudio2008上 编辑:好的,这是不起作用的代码。下面的函数是我调用new的地方,下面的是它下面的stackframes。最后一个函数是我有catch子句的地方,但是它没有在那里被捕获C++ std::bad_alloc没有在任何调用堆栈帧中被捕获,c++,try-catch,bad-alloc,C++,Try Catch,Bad Alloc,如果新操作符无法分配内存,只有在新语句周围立即放置try-catch块时,才会捕获异常std::bad_alloc。如果我在下面几帧的调用程序中使用try-catch块,它就不会在那里被捕获,我会得到一个异常的程序术语。为什么会发生这种情况?这是在MicrosoftVisualStudio2008上 编辑:好的,这是不起作用的代码。下面的函数是我调用new的地方,下面的是它下面的stackframes。最后一个函数是我有catch子句的地方,但是它没有在那里被捕获 void HTTPRespon
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;
}
}
void HTTPResponseBuff::grow()
{
如果(m_nmaxize>m_nStartConstGrowSize)
m_nMaxSize+=m_nConstrowSize;
其他的
m_nmaxize=2*m_nmaxize;
char*pTmp=新字符[m_nmaxize];
. . .
}
void HTTPResponseBuff::write(常量字符*pBuf,大小长度)
{
char*pCh;
同时(获取剩余产能(pCh)写入(pChar,respDataLen);
返回响应;
}
这里有几个框架。这些是C代码,不是C++。
ISTATUS HTTPTransport::invoke()
{
调用ecleanup();
//进行HTTP调用
卷曲编码和重编码;
试一试{
retCode=curl\u easy\u perform(m\u pCurl);
}
捕获(标准:错误分配和ba)
{
strcpy(m_pErrMsg,ba.what());
m_状态=IFAILURE;
}
}
另外,我捕获坏的alloc时的stackframes(在紧靠新语句的catch子句中)在这里:如果可能的话发布代码,在没有代码的情况下,我已经编写了一个小测试,try/catch似乎可以很好地工作,即使还有几个stackframe(该示例在gcc中也可以正常工作):
void foo()
{
int*myarray=newint[100000000];
}
void foo1()
{
int i=9;
foo();
}
void foo2()
{
int j=9;
foo1();
}
int main(){
尝试
{
foo2();
}
捕获(例外和e)
{
您提到了异常源和try-catch之间的第三方函数。
如果这些第三方函数不是c++(例如具有c链接,比如用c编写的libcurl),那么异常处理将不会像预期的那样工作
在回调通过第三方层传播之前,您需要捕获回调中的所有异常,并使用错误代码(或自定义机制)将信息输入调用方,或者完全放弃使用异常
当你问我做了什么时:我通过一个可用的空指针将调用方的上下文对象注入回调。因此我将上下文对象更改为具有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);
}
如果你不担心线程安全,你也可以使用全局变量
这样说,处理内存错误可能是很棘手的,因为你应该避免为错误消息分配额外的内存< /p>它是什么编程语言?它看起来是C++ + o.c++。它与调用堆栈中的函数没有“抛出的BADOL OLLC”有关吗?中间的STACKFrand是从第三方来的。你可以发布一个代码样本来展示这个行为吗?抛出的规范在C++中并不常用,在C++ 0x中不被推荐。我不会把它们添加到新的代码中。BADYOLLC用于内存不足的情况。可能不允许在抛出和捕获之间分配额外内存。这可能解释了为什么一个紧的try-catch有效,而大的try-catch失败。你可以看一下这张图片,而不是我发布代码,没有人在抛出和捕获之间分配额外内存。这只会如果LIGBRIL的中间帧从catch子句中捕获异常并分配内存,这是高度想象的,是的,中间堆栈帧确实是C,不是C++。如果异常处理不会像预期的那样工作,这会使事情变得复杂,因为问题在回调函数中是已知的,但是我怎么能知道呢?向下传播此信息,并停止程序的进一步执行?请告诉您在项目中做了什么?回调函数只有一个void返回类型。
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);
}