【问题标题】:Is calling delete operator on a memory allocated by new[] operator undefined behavior?是否在由 new[] 运算符未定义的行为分配的内存上调用 delete 运算符?
【发布时间】:2015-07-16 06:53:03
【问题描述】:

我很确定是这样,但如果我正确解释标准(第 18.6.1.2 节 new.delete.array)提到:

void operator delete[](void* ptr) noexcept; 指针。

13 默认行为:调用 operator delete(ptr)

因为在它的默认行为中 delete[] 只是调用它的 delete(ptr) 等效项,为什么调用哪个版本很重要? 我尝试使用示例代码来验证这一点,但它崩溃了,这更加明显地表明 new[] 和 delete 不匹配确实会导致坏事

#include <iostream>
#include <memory>
class foo{
    public:
        void bar(){
            std::cout << "foo's bar" << std::endl;
        }
        ~foo(){
            std::cout << "foo dies after this" << std::endl;
        }
};
int main() {
    std::shared_ptr<foo> x(new foo[10]);
    return 0;
}

应该如何解释上面引用的标准行?

【问题讨论】:

  • delete 不仅仅是调用::operator deletedelete[] 不仅仅是调用::operator delete[]。我不清楚你是否理解这一点。如果你这样做,你能编辑你的问题来解决它吗?
  • @LuchianGrigore 我知道以这种方式创建 shared_ptr 的麻烦。事实上,这就是我明确选择该示例的原因。我的主要问题是关于解释语言标准。
  • 很准确,它描述了库函数的操作。调用所有数组元素的析构函数是编译器的工作,而不是库函数。

标签: c++ standards c++14 delete-operator


【解决方案1】:

您将delete[] 表达式与函数operator delete[] 混淆了。当你写:

delete[] p;

然后编译器发出代码,该代码将为p指向的数组中的所有对象调用析构函数,然后使用参数p调用释放函数operator delete[]。根据您引用的文档,默认的::operator delete[] 调用::operator delete。因此,当使用默认实现时,以下对释放函数的调用是等效的:

::operator delete[] (p);
::operator delete(p);

但以下是等效的,因为它们不仅仅是调用释放函数:

delete[] p;
delete p;

【讨论】:

  • 谢谢。这澄清了我的问题:)
猜你喜欢
  • 2012-11-29
  • 2020-08-02
  • 2011-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
  • 1970-01-01
  • 2015-01-16
相关资源
最近更新 更多