2011-07-27 25 views
2

新しい演算子がメモリを割り当てられない場合、新しい命令をすぐに取り囲むtry-catchブロックを置くと例外std :: bad_allocが捕捉されます。代わりに、呼び出し側でtry-catchブロックをいくつか下にスタックすると、そこに捕捉されず、異常なプログラムのtermainationが発生します。なぜこれが起こるのですか?これはMicrosoft Visual Studio 2008にあります。std :: bad_allocが呼び出しスタックフレームで捕捉されない

編集:OK、ここでは動作していないコードです。すぐ下の関数は私が新しいものを呼び出す場所であり、以下のものはその下のスタックフレームです。最後の関数はcatch節があるところですが、そこに捕まえられません。また、私は(すぐに新しいステートメントを囲むcatch節で)bad_allocをキャッチ時点でStackFrameを

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; 
    } 
} 

はここにある: http://s289.photobucket.com/albums/ll211/spiderman2_photo_bucket/?action=view&current=bad_alloc.jpg

+0

ための追加のメモリを割り当てる避ける必要があるため、この方法は、トリッキーなことができ、メモリ不足エラーが取り扱い、言いましたか?それはC++のCのようです。 – reporter

+0

C++。コールスタック内の関数に "throws bad_alloc"が定義されていないという事実と関係がありますか?途中のスタックフレームの中にはサードパーティ製のものがあるので、このdelcarationを追加することはできません。 –

+4

この現象を示すコードサンプルを投稿できますか? –

答えて

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

1

あなたは、例外の原点とのtry-catchわたってるしきサードパーティの機能を述べました。 これらのthirdparty関数がC++でない場合(例えばlibcurlがcで書かれているようにcリンケージがある場合)、例外処理は期待どおりに機能しません。 gccを使ったプロジェクトでも同じ問題がありました。

コールバックですべての例外を捕捉してから、サードパーティのレイヤーに伝播し、エラーコード(またはカスタムメカニズム)を使用して呼び出し元に情報を取得するか、例外を完全に使用しないようにする必要があります。


私がしたことを尋ねる:呼び出し元からコンテキストオブジェクトをコールバックに注入して、空のポインタを使用できるようにしました。だから私は、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); 

} 

スレッドの安全性について心配していない場合は、グローバル変数も使用できます。

あなたは言語がそれであるprogrammarエラーメッセージ

+0

はい、中間スタックフレームは確かにCではなくC++です。例外処理が期待どおりに機能しない場合、コールバック関数で問題が分かっているために複雑になりますが、この情報を下位に伝播してプログラムの実行を停止するにはどうすればよいですか?あなたのプロジェクトで何をしたのか教えてください。コールバック関数はvoid型の戻り値のみを持ちます。 –

関連する問題