2016-03-26 11 views
-1

正常に動作するコードがありますが、例外処理を追加するとブレークします。私は初心者ですし、ここでこのコードは動作するコードcatchブロックの導入後に予期せずプログラムが終了する

です(簡潔のために警備員が示されていない含める):

plane.hで:

#include "vector.h" //which, like point.h, inherits from orderedpair.h 
class Plane { 
    public: 
     Plane(const std::string &label); 
     Plane(const Plane &); 
     virtual ~Plane(); 

     void insert(const OrderedPair &); 
     void label(const std::string & label); 
     std::string label() const {return _label;} 

    protected: 
     std::string _label; 
     bool operator==(const Plane &rhs) const {return label() == rhs.label();} 
     bool operator<(const Plane & rhs) const {return label() < rhs.label();} 
}; 

plane.cppで

#include <set> 
Plane::Plane(const std::string &label) : _label(label) { 
    getUniverse().insert(this); 
} 

/*GLOBAL OBJECTS*/ 

extern std::set<Plane *>& getUniverse() { 
    static std::set<Plane *>universe; 
    return universe; 
} 

extern Plane& getDefaultPlane() { 
    static Plane Default("Default"); 
    return Default; 
} 

void printworld() { 
    for (auto i : getUniverse()) 
     std::cout << (*getUniverse().find(i))->label() << std::endl; 
} 

とメインで:

//MinGW32 4.9 Code::Blocks 16.01 Windows Vista(!!) 64bit -std=C++11 
#include <iostream> 
#include "vector.h" //includes point.h which includes orderedpair.h 
#include "plane.h" 

using namespace std; 

namespace { 
    struct Initializer {; 
     Initializer(); 
    }; 
} 

int main() { 

static Initializer init; 
Point A("A", 1, 1); 

Plane P("P"); 
Plane duplicate("Default"); 

printworld(); 
return 0; 
} 

Initializer::Initializer() 
{ 
    // Trigger construction of the default Plane 
    getDefaultPlane(); 
} 

は、それから私はplane.hで例外を含め、先頭に次の行を追加します。

class E : public std::exception { 
    const char *msg = nullptr; 
public: 
    E(const char *m) throw() : msg(m) {} 
    const char *what() const throw() {return msg;} 
}; 
const E DuplicateObj("Object already exists!\n"); 

それは問題なく、コンパイルし、実行します。 は、それから私は(必ずラベルが以前に使用されていないにするために)、このように平面のコンストラクタを変更:

Plane::Plane(const std::string &label) : _label(label) { 
    for (auto i : getUniverse()) { 
      if ((*getUniverse().find(i))->label() == _label) throw DuplicateObj; 
    } 
    getUniverse().insert(this); 
} 

とメイン内の重複平面のインスタンス化をコメントアウト(スローをトリガーする避けるため)。コンパイルして実行しても問題ありません。

その後、私がメインでtry/catchブロック内のオブジェクトのインスタンス化の行を折り返す:

try { 
    Point A("A", 1, 1); 
    Plane P("P"); 
    //Plane duplicate("Default"); 
} 
catch (const E& e) { 
    cerr << e.what() << endl; 
} 
catch (const exception &e) { 
    cerr << e.what() << endl; 
} 

これは、コンパイルしますが、以下の結果にクラッシュ:

Process returned -1073741819 (0xC0000005) execution time : 9.537 s 
Press any key to continue. 
+0

プライベートのデフォルトコンストラクタは必要ありません。別のコンストラクタを指定すると、デフォルトのコンストラクタは無効になります。 –

+1

例外をスローするコードは表示されません。 –

+0

理想的には、完全でコンパイル可能なものを投稿してください。 – kec

答えて

0

は、例外の問題ではありません。

これはポインタとスコープの問題です。

私が間違っていない場合。

あなたの飛行機のコンストラクタ挿入(getUniverse().insert(this);)静的グローバルセット(getUniverse()static std::set<Plane *>universe;)でthisポインタ。

次に、最後の命令のグローバルセットをmain()printworld())で使用します。

try/catchブロックが導入される前に、Plane P("P");オブジェクトの有効範囲は、完全なmain()です。 printworldを呼び出すとPへのポインタが有効なポインタになります。

しかし、あなたは

try { 
    Plane P("P"); 
    // end of P scope 
} 

// P is out of scope; the pointer to P, in universe, is invalid 

printworld(); // use of a invalid pointer to P 

を書くときPの範囲は、唯一tryブロックです。したがって、printworld()tryブロックの外に呼び出すと、universeには破棄されたオブジェクトへのポインタが含まれています。

クラッシュ!

p.s .:申し訳ありませんが、私の悪い英語です。

+0

これはまさに問題です!問題は範囲にあるとわかっていましたが、正確に何かを理解できませんでした。あなたは頭の爪を打つ!どうもありがとう!ヒープからPを宣言する以外の方法はありませんか? @ max66 –

+0

他の方法があるかどうかわかりません。 'universe'はポインタを使用するので、ポインタが有効であることを確認する必要があります。この場合、 'new' /' delete'を使うか、 'try'ブロックの中で' printworld'を使うことができます – max66

関連する問題