1

下面的代码创建一个指向 a 的双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

听起来不错。

的类型fbB**所以的类型*fbB*

因此,当您说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 回答