在自动对象上调用delete

时间:2012-11-20 16:55:39

标签: c++

考虑以下c ++代码:

class test
{
public:
    int val;

    test():val(0){}
    ~test()
    {
        cout << "Destructor called\n";
    }
};

int main()
{
    test obj;
    test *ptr = &obj;
    delete ptr;

    cout << obj.val << endl;

    return 0;
}

我知道只应在动态分配的对象上调用delete,但现在obj会发生什么?

好的,我知道我们不应该做这样的事情,现在如果我正在编写智能指针的以下实现,我怎样才能确保这样的事情不会发生。

class smart_ptr
{
public:
    int *ref;
    int *cnt;

    smart_ptr(int *ptr)
    {
        ref = ptr;
        cnt = new int(1);
    }

    smart_ptr& operator=(smart_ptr &smptr)
    {
        if(this != &smptr)
        {
            //  House keeping
            (*cnt)--;
            if(*cnt == 0)
            {
                delete ref;
                delete cnt;
                ref = 0;
                cnt = 0;
            }

            //  Now update    
            ref = smptr.ref;
            cnt = smptr.cnt;
            (*cnt)++;
        }
        return *this;
    }

    ~smart_ptr()
    {
        (*cnt)--;
        if(*cnt == 0)
        {
            delete ref;
            delete cnt;
            ref = 0;
            cnt = 0;
        }
    }
};

5 个答案:

答案 0 :(得分:3)

您在帖子中提出了两个不同的问题。我会另外回答。

  
    

但是现在obj会发生什么?

  

您的计划的行为是未定义。 C ++标准没有对obj现在发生的事情发表评论。事实上,该标准也没有评论你的程序之前错误。它只是未定义

也许您的编译器供应商会对发生的事情做出承诺,也许您可​​以检查程序集并预测会发生什么,但C ++,本身,并未定义会发生什么。

从实际上说 1 ,您可能会收到来自标准库的警告消息,或者您将获得seg错误,或两者兼而有之。

1:假设您在Windows或具有MMU的类UNIX系统中运行。其他规则适用于其他编译器和操作系统。


  
    

如何确保不会发生[delete堆栈变量]。

  

永远不要使用堆栈变量的地址初始化smart_ptr。一种方法是将接口记录到smart_ptr。另一种方法是重新定义接口,以便用户永远不会将指针传递给smart_ptr;让smart_ptr负责调用new

答案 1 :(得分:1)

您的代码具有未定义的行为,因为您在未使用new分配的指针上使用了delete。这意味着任何事情都可能发生,并且不可能说出obj会发生什么。

我会猜测在大多数平台上你的代码会崩溃。

答案 2 :(得分:1)

删除尝试访问内存中的obj空间,但操作系统不允许执行此操作并抛出(核心转储)异常。

答案 3 :(得分:0)

未定义会发生什么,所以你不能说太多。您可以做的最好的是推测特定的实现/编译器。

答案 4 :(得分:0)

这不仅仅是未定义的行为,如其他答案所述。这几乎肯定会崩溃。

第一个问题是尝试释放堆栈变量。

第二个问题将发生在程序终止时,test将为obj调用析构函数。