删除此指针时堆栈溢出

时间:2014-01-24 06:53:38

标签: c++ stack

我有以下代码,我得到堆栈溢出错误任何人都可以请解释我这里有什么问题。从我的理解,这个指针指向当前对象,所以为什么我不能在析构函数中删除它;

class Object 
{
private:
    static int objCount;
public:
    int getCount()
    {
        int i =10;
        return i++;
    }
    Object()
    {
        cout<< "Obj Created = "<<++objCount<<endl;
        cout <<endl<<this->getCount()<<endl;
    }
    ~Object()
    {
        cout<<"Destructor Called\n"<<"Deleted Obj="<<objCount--<<endl;
        delete this;
    }
};

int Object::objCount = 0;

int _tmain(int argc, _TCHAR* argv[])
{


    {
        Object obj1;
    }

    {

              Object *obj2 = new Object();
    }
    getchar();
    return 0;
}

4 个答案:

答案 0 :(得分:15)

你在班级的析构函数中正在做delete this;

好吧,delete调用了类的析构函数。

你在班级的析构函数中正在做delete this;

...


<!<!<!Stack Overflow!>!>!>

(对不起家伙,我觉得有必要把它包括在内......这可能会破坏它的悲伤性!

无聊故事的道德,不要在你的析构函数delete this;Object *obj = new Object(); delete obj;

[1]

Object obj;

或更好,只是

obj1

[1] or don't do it at all!更准确地指出堆栈溢出实际上是由{{1}}的析构函数触发的。

答案 1 :(得分:3)

'删除这个'永远不会有意义。你要么在这里引起无限递归,要么你正在删除某个对象,而它还在被其他人使用。只需删除它。该对象已被删除:这就是你在析构函数中的原因。

答案 2 :(得分:3)

您遇到的崩溃是由于以下声明:

{
    Object obj1;
}

这会在堆栈上分配“对象”的实例。您创建它的范围结束,因此对象超出范围,因此调用析构函数(Object :: ~Object)。

{
    Object obj1;
    // automatic
    obj1.~Object();
}

这意味着应用程序将遇到的下一条指令是

delete this;

这里有两个问题:

  1. delete调用对象的析构函数,因此析构函数间接调用析构函数,间接调用析构函数...
  2. 在析构函数调用之后,delete尝试将对象的内存返回到new从中获取它的位置。
  3. 相比之下

    {
    
              Object *obj2 = new Object();
    }
    

    这会创建一个堆栈变量obj2,它是一个指针。它在上分配内存来存储Object的实例,调用它的默认构造函数,并将新实例的地址存储在obj2中。

    然后obj2超出范围,没有任何反应。 Object没有被释放,也没有被调用的析构函数:C ++没有自动垃圾收集,并且当指针超出范围时没有做任何特殊事情 - 它肯定不会释放内存。

    这是内存泄漏。

    经验法则:delete来电应与new来电相匹配,delete []new []相匹配。特别是,请尝试将newdelete保留在匹配的权限区域中。以下是不匹配的所有权/权限/责任的示例:

    auto* x = xFactory();
    delete x;
    

    同样地

    auto* y = new Object;
    y->makeItStop();
    

    相反,你应该更喜欢

    // If you require a function call to allocate it, match a function to release it.
    auto* x = xFactory();
    xTerminate(x); // ok, I just chose the name for humor value, Dr Who fan.
    
    // If you have to allocate it yourself, you should be responsible for releasing it.
    auto* y = new Object;
    delete y;
    

    C ++有容器类,可以为您管理指针的对象生存期,请参阅std::shared_ptrstd::unique_ptr

答案 3 :(得分:1)

这里有两个问题:

  1. 您正在使用delete,这通常是代码气味
  2. 您正在使用delete this,这有几个问题

  3. 指南:您不应使用newdelete

    <强>原理

    • 明确地使用delete而不依赖于智能指针(并且通常是自动清理)脆弱,不仅原始指针的所有权不清楚(你确定应该删除它吗?)但是还不清楚你是否真的在每个需要它的 上调用delete尤其是在存在异常< / em> =&gt;做你的理智(以及你的同伴的理智),不要使用它。
    • 使用new也容易出错。首先,您确定需要在堆上分配内存吗? C ++允许在堆栈上进行分配,C ++标准库具有容器(vectormap,...),因此需要动态分配的实际实例很少且很远。此外,如上所述,如果你达到动态分配,你应该使用智能指针;为了避免执行问题的微妙顺序,建议您使用工厂函数:make_sharedmake_unique(1)来构建所述智能指针。

      (1)make_unique在C ++ 11中不可用,仅在C ++ 14中,它可以通过以下方式实现(使用new,当然:p)


    指南:您不得使用delete this

    <强>理由:

    使用delete this意味着,从字面上看,锯掉了你所坐的分支。

    • delete的参数应始终是动态分配的指针;因此,如果您无意中在堆栈上分配了最有可能导致程序崩溃的对象实例。
    • 该方法的执行继续通过此语句,例如将执行本地对象的析构函数。这就像走在物体的鬼魂上,不要往下看!
    • 如果包含此语句的方法抛出异常或报告错误,则很难评估对象是否已成功销毁;并且再次尝试不是一种选择。

    我已经看到了几个使用示例,但没有一个不能使用传统的替代方案。