【问题标题】:C++ can operator delete fails and if not why?C ++可以运算符删除失败,如果不是,为什么?
【发布时间】:2015-04-06 16:36:08
【问题描述】:

operator delete 能否在内存释放期间抛出异常或以其他方式的错误信号?

另外,operator delete 是否有可能失败,在这种情况下它的默认行为是什么?

ISO 标准对此有何规定?

例如在 Windows 操作系统中 - C++ operator newoperator delete 通常通过函数 HeapAllocHeapFree 实现。后面的函数返回一个布尔值,清楚地表明失败是可能的。想象一下 C++ operator delete 将如何写在上面:

void operator delete(void *pMem)
{
    extern HANDLE hHeap;
    extern DWORD dwFlags;

    BOOL bSuccee = HeapFree(hHeap, dwFlags, pMem);

    //return bSuccee ????????????
}

【问题讨论】:

  • cplusplus.com/reference/new/operator%20delete%5B%5D 会有所帮助。保证不会投掷任何球。删除后指针无效。
  • 老实说,这有点像比较苹果和橙子......看起来你的问题是 为什么 C++ 不允许 operator delete 以确定的行为失败,因为某些操作系统有允许这样做的设施吗? 那么答案将是因为 C++ 可以在许多其他操作系统上运行。
  • 你不能写一个返回的操作符删除,因为这是非标准的。
  • @Frédéric Hamidi 这就是我不明白为什么不存在返回布尔值或抛出异常的重载的原因。
  • @FISOCPP,在不支持这种设施的操作系统上会发生什么?显然delete 是否返回某些东西不能依赖于实现(那么你将有两种不同的语言)。如果delete 是否能够抛出依赖于实现......我认为任何“真正的”C++ 程序都不能可移植地运行。所以,它是最小公分母。

标签: c++ winapi iso delete-operator


【解决方案1】:

在 C++11 18.6 中,delete 被定义为 noexcept 函数。从第 5.3.5 节删除

如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并在本节的其余部分使用转换后的操作数代替原始操作数。在第一种选择(删除对象)中,delete 的操作数的值可以是空指针值,指向由先前的 new 表达式创建的非数组对象的指针,或指向表示 a 的子对象 (1.8) 的指针这种对象的基类(第 10 条)。 如果不是,则行为未定义。在第二种选择(删除数组)中,delete 的操作数的值可能是空指针值或前一个数组 new-expression 产生的指针值。82 如果不是,则行为未定义。 [ 注意:这意味着 delete-expression 的语法必须与 new 分配的对象的类型匹配,而不是 new-expression 的语法。 ——尾注

强调我的

从这里我们可以看出以不打算使用的方式使用删除是 UB。

【讨论】:

  • 我的意图是别的。如果此时内存无法释放怎么办?然后怎样呢?就像输入没问题,但功能无法完成任务。
  • 如果内存不能被解除分配,那对我来说是操作系统问题,而不是 C++ 的权限
  • @Frédéric Hamidi 我说的是“无法解除分配”而不是“无法分配”。
  • @NathanOliver 但是为什么分配内存失败不是操作系统问题?
  • @NathanOliver:“无法解除分配”的示例:位于分配内存之前的元数据块已被数组溢出损坏。不涉及操作系统。但在这种情况下,已经发生了未定义的行为。我相当肯定解除分配失败只会发生在其他形式的 UB 之后。
【解决方案2】:

运算符delete自C++11起就是noexcept,所以不会抛出,见http://en.cppreference.com/w/cpp/memory/new/operator_delete

如果操作员delete 抛出,那么你最终可以在析构函数中抛出,并且所有的赌注都被取消了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-12
    • 2021-08-08
    • 2013-09-01
    • 2019-07-05
    • 2019-08-04
    • 2011-04-19
    • 2010-09-16
    相关资源
    最近更新 更多