C++ delete[] on new char;

C++ delete[] on new char;

本文关键字:new char on delete C++      更新时间:2023-10-16

考虑以下代码:

int main()
{
    char* str = new char; 
    str[0] = 'a'; 
    delete[] str; //Notice the []
}

它编译,运行,没有崩溃(VC15和g++)但是,它确实有1个内存泄漏,我可以清楚地看到与valgrind。

如果我运行下面的代码:
#include <iostream>
class Foo{
public:
    Foo(){
        std::cout << "Foo::Foo" << std::endl;
    }
    ~Foo(){
        std::cout << "Foo::~Foo" << std::endl;
    }
};
int main()
{   
      Foo* foo = new Foo;
      delete[] foo;
      return 0;
}

在Windows上运行时,我得到一个析构函数调用的无限循环,并且在Linux中出现一个无效的指针错误(在~20 d'tors调用之后)。

我不明白的是为什么这两者之间有区别?为什么我没有得到一个无限循环与new char或崩溃?

您应该将delete[]与且仅与使用new[]分配的指针一起使用;

在第一个代码片段中:

  • 使用char* str = new char;语句,您可以获得指向单个字符的指针。所以来自new的类型匹配char*
  • 但是你的delete[]期望一个指向char数组的指针,所以当你删除一些不是数组的东西时,你会得到未定义行为(UB)

第二个代码片段有完全相同的问题。UB是未定义的,可以给出奇怪和无法解释的结果。

如何解决

为单个元素分配使用单个元素delete:

  Foo* foo = new Foo;
  delete foo;

或者使用数组delete来分配数组:

  Foo* foo = new Foo[1];
  delete[] foo;

或者更好:去掉你想要使用的new/delete,用vector代替数组。

简而言之,对于没有分配new[]且不是null的指针调用delete[]总是undefined

我引用自cppreference.com:

由delete[]-表达式调用,释放先前为对象数组分配的存储空间。行为的标准该函数的标准库实现是未定义的,除非ptr是null指针或先前从标准中获得的指针operator new或operator的库实现新[](size_t, std:: nothrow_t)。