1

静的初期化でクラッシュ(デバッグアサーションの失敗:VC ++ 2008の無効なCRTヒープポインター)が発生しますが、その理由がわかりません。

C ++ FAQ静的初期化の大失敗についてすべて読んだのですが、それを理解したと思いました。なぜこれが起こっているのか、なぜ大失敗の場合なのかわかりません。

これが状況です(簡潔にするために、ほとんどの非静的メンバーは省略されています)。Ahで定義されたクラスAが1つあります。

class A {
public:
    virtual ~A() { }

    virtual void do_something();
};

次に、AのサブクラスであるネストされたクラスBを持つクラスCがあります。Cには、タイプBのプライベート静的メンバーも含まれています。

class C {
public:
    void do_the_C_thing();

private:
    class B : public A {
    public:
        virtual void do_something();
    };

    static B my_personal_B;
};

最後に、my_personal_Bのストレージユニットを含むCの実装ファイルC.cppがあります。

C::B my_personal_B;

C::C() {
}

C::do_the_C_thing() {
    // [...]
    my_personal_B.do_something();
    // [...]
}

void C::B::do_something() {
    // overridden do_something for C's private B class
}

このパターンは多くのクラスで繰り返され、それぞれにAから継承するネストされたクラスがあります。これはすべて、いくつかのコードリビジョンを通じて問題なく動作していますが、最近、アプリケーションが次の特定のエラーメッセージでクラッシュします。

デバッグアサーションに失敗しました!

プログラム:
[編集済み] .exe
ファイル:f:\ dd \ vctools \ crt_bld \ self_x86 \ crt \ src \ dbgheap.c
行:1511

式:_CrtIsValidHeapPointer(pUserData)

クリックしてデバッグすると、静的メンバーが定義されているC.cppの行が表示されます。

これは静的な大失敗のようには見えません。静的なものはmy_personal_Bを参照せず、AもBもデフォルトのコンストラクターしか持たないため、まだ初期化されていない他の静的オブジェクトを参照できない可能性があります。私が大失敗を理解した方法は、ある静的オブジェクトがまだ初期化されていない別の静的オブジェクトを参照したときに発生したということです。

それでも、静的メンバーを初回使用時の初期化メソッドに変更すると、クラッシュは解消されたように見えます。

だから問題は、なぜこれがクラッシュするのかということです。

4

2 に答える 2

2

クラスAには仮想機能があります。つまり、コンパイラは、メンバー関数へのポインタを保持するためにvtableと呼ばれる静的オブジェクトを生成します。したがって、クラスAで静的オブジェクトを定義していなくても、コンパイラーは定義する必要があります。クラスBはそのvtableに依存します(Aの仮想デストラクタの場合、他に何もない場合)。どうやら、初期化コードは、Aのvtableが構築される前に、タイプBのオブジェクトを作成しようとしているようです。

于 2012-09-28T20:43:22.257 に答える
-1

おい、そもそもなぜ静的初期化に依存しているのですか?「デザインエラー」と言えますか?

提案:

デザインを変更できない場合は、少なくともフラグ「bInitialized」を設定して、依存するクライアントがオブジェクトが実際に初期化されているかどうかを確認し、正常に失敗できるようにしてください。

私見では...

于 2012-09-28T20:11:29.340 に答える