删除已删除的对象:行为?

时间:2011-12-14 08:58:52

标签: c++ pointers memory-management delete-operator

我想知道如果我尝试对已经删除但可能尚未分配的指针执行delete会有什么影响?我读过两件事:第一,delete运算符会做一些检查,我们不需要检查指针是否为空;然后,我读到它会导致未知的行为..

我问它,因为我使用了一些包含Qt对象属性的个人对象;我认为Qt会删除关闭窗口时关联的所有小部件,但我不确定并且仍然如此:如果在窗口关闭之前软崩溃,我们必须手动删除所有对象。

那么,什么是最好的解决方案?那样的东西?

if( my_object )
    delete my_object;

可以避免危险行为吗?

6 个答案:

答案 0 :(得分:14)

已经delete d非空指针上的

delete是未定义的行为 - 您的程序可能会崩溃。您可以安全地在空指针上使用delete - 它将产生一个无操作。

所以真正的问题不是空指针上的delete。真正的问题在于:

 ptr = new Something();
 otherPtr = ptr;
 delete ptr;
 delete otherPtr;

如果您有多个指向同一个对象的指针并且非常危险,则会发生这种情况。可能的解决方案是:

  • 使用智能指针(代码中没有delete)或
  • 只有一个指定的指针用于控制每个对象的生命周期,而delete恰好在恰当的时间。

答案 1 :(得分:4)

if( my_object )
    delete my_object;

是多余的。 delete指针上的NULL什么都不做。这是由标准保证的。

对已经删除的指针的

delete会导致未定义的行为。这就是为什么你应该总是记得在删除它们之后将指针分配给NULL

delete p;
p = NULL;

编辑:根据评论,我觉得我应该指明这一点。如果您有多个指向同一对象的指针,则赋值为NULL将不会使删除安全。无论如何,最好使用智能指针。

答案 2 :(得分:1)

请注意,删除指针不会将其设置为NULL。

int* i = new int;
*i = 42;
delete i;
delete i; // oops! i is still pointing to the same memory, but it has been deleted already

删除空指针不会执行任何操作,删除已删除的对象将导致未定义的行为。

答案 3 :(得分:1)

正确的方法是:

if( my_object )
{
    delete my_object;
    my_object = NULL;
}

因为,以前的方式调用两次会在delete指针上调用deleted

答案 4 :(得分:0)

如果您在已经delete d指针上调用delete,则会导致未定义的行为。 尽管在delete指针上调用NULL没有效果。

标准c ++03§3.7.4.2-3

  

如果通过抛出异常终止释放函数,则行为未定义。提供给解除分配函数的第一个参数的值可以是空指针值;如果是这样,并且如果解除分配功能是标准库中提供的功能,则该呼叫无效。否则,提供的值   标准库中的运算符delete(void*)应该是先前调用标准库中的运算符new(std::size_t)operator new(std::size_t, const std::nothrow_-t&)返回的值之一,并且值提供给运算符{{1标准库中的标签库应该是前一次调用delete[](void*)或者返回的值之一   标准库中的operator new[](std::size_t)

使用 RAII&智能指针是避免此类问题的最佳武器。

答案 5 :(得分:0)

只是结合上面的答案:

  • if(my_object)检查指针的值,而不是对象的存在。如果它已被删除,指针仍可指向该位置。
  • 删除已删除的对象是未定义的行为,可能会导致程序崩溃。
  • 已定义删除NULL并且不执行任何操作。与第1点一起,这解释了Luchian的答案。

总结一下:您必须清楚谁拥有该对象以及指向该对象的不同指针所在的位置。删除对象时,请确保将指向该位置的所有指针都设置为0 / NULL。使用管理对象(如boost :: shared_pointer或QPointer)来帮助您完成此任务。