2009-05-12 27 views
4

私はVisual Studioを使用しており、有効な動的キャストを行っています。 RTTIが有効になります。いつ、なぜstd :: __ non_rtti_object例外が生成されますか?

編集:より現実的なように、コードを更新しました

struct base 
{ 
    virtual base* Clone() 
    { 
     base* ptr = new base; 
     CopyValuesTo(ptr); 
     return ptr; 
    } 
    virtual void CopyValuesTo(base* ptr) 
    { 
     ... 
    } 
    virtual ~base() 
    { 
    } 
} 

struct derived : public base 
{ 
    virtual base* Clone() 
    { 
     derived* ptr = new derived; 
     CopyValuesTo(ptr); 
     return ptr; 
    } 
    virtual void CopyValuesTo(base* ptr) 
    { 
     ... 
    } 
    virtual ~derived() 
    { 
    } 
} 

void Class1::UseNewSpec(base* in_ptr) //part of a totally unrelated class 
{ 
    derived* ptr = dynamic_cast<derived *>(in_ptr); 
    if(!ptr) 
     return; 
    delete m_ptr; 
    m_ptr = ptr->Clone(); //m_ptr is a member of Class1 of type base* 
} 

//usage : 
Class1 obj; 
derived new_spec; 
obj.UseNewSpec(&new_spec); 

私のデバッガは、例外がスローされたときin_ptrが正しい型であることを述べています。 Googleは特に役に立たないようだ。何か案は?乾杯。

+0

実際のコードを投稿してください。 – dirkgently

+0

ここに使用シナリオがあります: UseNewSpecはGUIノブにリンクされています。ノブを変更すると、UseNewSpecが呼び出されます。それは、ノブがゆっくりと動いたときに機能しますが、実際に速く動いたときにはこの例外を表示します。 – Carl

+0

ありがとうございます。私はそれを理解した。これはスレッドの問題でした。他の場所のコードでは、ダイナミックキャストの直前にポインタが無効になっていました。 – Carl

答えて

5

あなたの擬似コードに基づいてテストを実行しました。これは動作します。 RTTIが本当にあなたのビルド構成で有効になっているならば、投稿したものには捕捉されない別の問題でなければなりません。

+3

誰かが将来この投稿に遭遇した場合、私は同様の問題を抱えていました。私は自分のコードで何か愚かなことをしていました: 'dynamic_cast'から返された(有効で非NULLの)後で同じ元のポインタ上で 'dynamic_cast'を呼び出すことに進みました。これはおそらくこの質問の問題ではありませんが、他の誰かがこの質問に簡単に何か問題があるかどうかを知るために、これを指摘しています。 –

+2

それは私にとって非常に似た問題でした。違いは、私が使用していたポインタを削除していたいたずらなコードがポインタをNULLに設定していないことでした。したがって、それは有効と見えましたが、動的キャストはまだ失敗しました。 – Carl

+2

は皆さんと同じ問題を抱えていました。ダングリングポインタで 'dynamic_cast <>'を呼びます。ありがとう – azf

5

dynamic_castの周りの例外、失敗、またはエラーは、あなたが不正なキャストを実行したことを意味する可能性があります。 dynamic_cast<derived*>(ptrToBase)は、クラスderivedとクラスbaseが両方とも次の制約を満たしている場合にのみ有効です。そのクラスまたはその基本クラスの1つに仮想メンバー関数があります。

この仮想メンバー関数は、デストラクタを含むすべてのものにできます。

struct base 
{ 
    virtual ~base(){} 
    ... 
} 

struct derived : public base 
{ 
    ... 
} 

今すぐbaseが仮想メンバ関数を持っており、その派生ん:あなたは、他のメンバ関数を持っていない場合、あなたは試すことができます。それを試して問題が解決するかどうかを確認してください。

EDIT-ADD:

@carleeto - で、それをDOE ==ベース "はすでに仮想デストラクタを持っていましたか"?

派生には仮想デストラクタがありますが、ベースは仮想以外のdtorである場合でも、このエラーが発生することがあります。

また、オブジェクトが破棄されていないことを確認する必要があります。デストラクタが実行されると、dynamic_castは安全に呼び出すことができなくなります。 ctorsとdtorsにトレースを追加してみてください。

+0

既に仮想デストラクタがありました。私のせいで、私はそれを示していたはずです。 – Carl

+0

@carleeto - 編集追加、新しい回答を参照 – Aaron

0

baseにはいずれもvirtualの方法が含まれていますか? dynamic_castを動作させるために必要です。

+0

はい、あります。申し訳ありませんが、コードに追加する必要があります。 – Carl

+0

私はちょうどコードを更新しました。 – Carl

8

http://msdn.microsoft.com/en-us/library/fyf39xec(VS.80).aspxには__non_rtti_object_exceptionに関する情報があります。 MSDNから

ポインタが 有効なオブジェクトを指していない場合、__non_rtti_objectexceptionは は(アクセス 違反など)の障害を引き起こしていることRTTIを分析する 試みを示し、スローされ、オブジェクトは なので無効です(不正なポインタまたは のコードは/ GRでコンパイルされませんでした)。

+0

/GRは、RTTIを有効にすることを意味します。デフォルトではすでに有効になっています。/GR-それをオフにします。明示的に/ GRをコマンドラインに追加しても、助けにはなりません。 – Carl

1

すべてのソースファイルでRTTIが有効になっていることを二重に確認してください。

ポインタが無効です。

関連する問題