2012-04-11 1 views
1

私が投げた例外クラスの動作は非常に奇妙です(少なくとも私にとって)。私は、例外クラスのコンストラクタ内の文字列にnewを介してメモリを割り当て、文字でそれを埋めています。これまでのところすべてが問題ありません。コードをデバッグするとき、私はVisual Studioでポインタが実際に正しい内容を持っていることがわかります。catchポインタの内容がキャッチブロックに渡されている間に削除されているようです

今、奇妙なことが起こります。私の次のブレークポイントは、構築後に例外が渡されるcatchブロックにあります。ここでは、例外オブジェクトに含まれる文字列の内容が壊れていることをデバッガで確認できます。アドレスはまったく変わっていませんでしたが!それで、文字列の内容が破壊されるようです。

私は例外デストラクターにブレークポイントを入れて、本当にcatchブロックが入る前に呼び出されています。 catchブロックを参照して例外を渡すことを学んだので、これは私をたくさん混乱させます。場合

#include <iostream> 
#include <cstring> 

class test_exception { 
public: 
    test_exception(); 
    ~test_exception() { 
     delete[] _msg; 
    } 

    // Getter Functions 
    char* errorMessage() const { 
     return _msg; 
    } 
private: 
    char* _msg; 
}; 

test_exception::test_exception() 
{ 
    _msg = new char[22]; 
    strcpy(_msg, "This is a test string"); 
} 

int main(int argc, char* argv[]) 
{ 
    try { 
     throw test_exception(); 
    } catch (const test_exception& err) { 
     std::cout << err.errorMessage() << std::endl; 
    } 

    std::cin.get(); 

    return 0; 
} 

それが作成されます。しかし、何が良い私は、動的に作成されたデータにアクセスすることができます前に、デストラクタが呼び出された場合ということ...

私は私は状況がで示し、最小限の例を構築しました誰かが私に奇妙なMSの動作であるか、try-catchブロックをどのように使用すべきか誤解しているかどうかを教えてくれました。

答えて

3

例外がスローされたときに、例外がコピーされます(またはC++ 11で移動される可能性があります)。

スロー発現一時オブジェクトを初期化し、例外オブジェクト、任意のトップレベルCV-を除去することによって決定されたタイプと呼ばれる:C++ 11、§15.1/ 3を引用修飾子をスローのオペランドの静的型から取り出し、 "Tの配列"または "Tを返す関数"から "Tへのポインタ"または "Tを返す関数へのポインタ"に型を調整します。テンポラリは左辺値で、一致する名前の変数に初期化するために使用されます。例外オブジェクトの型が不完全型または不完全型へのポインタ(おそらくcv修飾されたもの)void以外の場合、プログラムは不正です。これらの制限および15.3で述べた型マッチングの制限を除き、throwのオペランドは、コールまたはreturn文のオペランドの関数引数として正確に扱われます。

test_exceptionrule-of-three(またはC++ 11、rule-of-five用)に違反しているため、test_exception::_msgはすでに、あなたのcatchブロックを入力し、時間によって削除されました。

+0

ありがとうございました!私はそれを知らなかった。 catchブロックで参照を使用していたので、例外をスローするときに作成したオブジェクトを使用していると思っていました。もちろん、これで説明します。また、リンクをありがとう! – Cyianor

0

例外がコピーされるため、test_exceptionオブジェクトにコピーコンストラクタを追加する必要があります。 を投げた例外は、キャッチが受け取ったものと同じものではなく、ではありません。

関連する問題