请考虑以下代码:
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&#39; tors调用之后)。
我能弄清楚的是为什么两者之间存在差异?为什么我没有new char
或崩溃的无限循环?
答案 0 :(得分:5)
您应使用delete[]
并且仅使用使用new[]
分配的指针;
问题
在您的第一个代码段中:
char* str = new char;
,您将获得指向单个字符的指针。所以新的类型匹配char*
。 delete[]
需要一个指向char数组的指针,所以当你删除一个不是数组的东西时你会得到未定义的行为(UB)第二个代码段有完全相同的问题。 UB未定义,可以给出奇怪和无法解释的结果。
如何解决?
对单个元素分配使用单个元素delete:
Foo* foo = new Foo;
delete foo;
或者使用数组删除进行数组分配:
Foo* foo = new Foo[1];
delete[] foo;
或更好:摆脱任何你想要使用的新/删除并使用向量而不是数组。
答案 1 :(得分:1)
要做到这一点,请调用delete[]
以获取未使用new[]
而非null
分配的指针始终 undefined 强>
我引用cppreference.com:
由delete []调用 - 表达式,用于释放先前为对象数组分配的存储空间。标准的行为 除非ptr是,否则此函数的库实现未定义 空指针或是先前从标准获得的指针 operator new或operator的库实现 new [](size_t,std :: nothrow_t)。