从析构函数中调用delete会导致堆栈溢出吗?

时间:2012-06-14 06:37:16

标签: c++ memory-management stack-overflow destructor

以下代码为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()时,我都会出现堆栈溢出!

3 个答案:

答案 0 :(得分:7)

听起来不错。

fb的类型为B**,因此*fb的类型为B*

所以当你说delete *fb你正在调用class B的析构函数时,这是一个递归调用,它没有向基本情况发展,因此堆栈溢出。

答案 1 :(得分:6)

B()中,您指定*fb = this;,然后指定:

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

..相当于一次又一次地在析构函数delete this;内调用~B(),因此由于递归函数过多而导致堆栈流。

这是Is it safe to delete this的一个很好的主题。

答案 2 :(得分:4)

这并不奇怪。你在B类的析构函数中,访问当前正在调用析构函数的B的SAME实例,然后再次删除它。这将导致析构函数调用中的递归,从而导致堆栈溢出。你在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;
    }