1

次のコードは、への double ポインターB**を作成しますB*。そのポインターを使用して、呼び出さBれたときに作成されたインスタンスを指す別のポインターにメモリを割り当てます。start()

class A:

class A
{
public:
    A()
    {
        fb = new B*;
        *fb = NULL;
    }

    ~A()
    {
        if(*fb)
            delete *fb;

        delete fb;
    }

    B** getfb()
    {
        return fb;
    }

private:
    B** fb;
};

class B:

class B
{
public:
    B()
    {
        B** fb = a->getfb();

        *fb = this;
    }

    ~B()
    {
        B** fb = a->getfb();

        delete *fb;            // <--- stack overflow

        *fb = NULL;
    }

private:
    A* a;
};

start()( のメンバー関数class C):

void C::start()
{
    B** fb = a->getfb();        // 'a' is a pointer to an 'A' instance

    if(*fb == NULL)
        B* f = new B;
}

start()そのため、 を呼び出してからを呼び出すたびに~B()、スタック オーバーフローが発生します。

4

3 に答える 3

7

そうですね。

の型はfbですB**ので の型は*fbですB*

したがって、基本ケースに向かって進行しない再帰呼び出しであるdelete *fbデストラクタを呼び出していると言うと、スタックオーバーフローが発生します。class B

于 2012-06-14T06:39:56.857 に答える
6

割り当てB()*fb = this;から:

~B()
{
  ...
  delete *fb; // delete this;
  ...
}

..はdelete this;、デストラクタ内~B()を何度も呼び出すことと同じであり、再帰関数が多すぎるためにstackoveflowが発生します。

これは、安全ですか?delete thisの素敵なスレッドです。

于 2012-06-14T06:42:06.247 に答える
4

これは驚くべきことではありません。クラス B のデストラクタ内にいて、現在デストラクタが呼び出されている B の同じインスタンスにアクセスしてから、再度削除します。これにより、デストラクタ呼び出しで再帰が発生し、スタック オーバーフローが発生します。クラスAによるfbの削除は、クラスBがそれ自体を削除したくない場合にメモリをクリーンアップするのに十分です。

また、クラス B コンストラクターで行っていることを行う必要もありません。クラス A のコードは理にかなっていますが、クラス B のコードは危険で不必要です。クラス B には、そのメンバー a を設定する機能がありません。これは、ポインターが初期化されていないことを意味し、クラス B のこのインスタンスを、この初期化されていないA のインスタンスのクラス B のメンバー ポインターに割り当てようとします。

    B()
    {
        B** fb = a->getfb(); // a never gets set to a meaningful value!!!!!

        *fb = this;
    }
于 2012-06-14T06:43:47.567 に答える