为什么在类对象数组上调用delete而不是delete []会导致堆损坏? [英] Why does calling delete instead of delete[] on an array of class objects cause heap corruption?

查看:189
本文介绍了为什么在类对象数组上调用delete而不是delete []会导致堆损坏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑代码:

class A {
public:
    virtual ~A() {}
};

class B : public A {
public:
    ~B() {}
};

void main ()
{
    A * array = new A[100];
    delete array;
}

在Windows上(MSVC 2010),它会导致异常,因为 delete 调用 HeapValidate ,这表示堆已损坏。

On Windows (MSVC 2010), it causes exception because delete calls HeapValidate, which then indicates the heap was corrupted. How and why does this happen?

我真的意识到 delete [] 应该在这里调用,没有问题。但是为什么 delete 会导致堆损坏?据我所知,它应该为第一个对象( array [0] * array )调用析构函数然后释放整个块。在现实中会发生什么?

I indeed realize delete[] should be called here, and of course then there is no problem. But why does delete cause heap corruption? As far as I know, it should call a destructor for the first object (array[0] or *array) and then free the whole block. What happens in reality?

注意:如果类 A 只有默认析构函数,即我根本不声明它的析构函数,异常不会发生。无论析构函数是否是虚函数。在调试和发布版本中。

Note: if class A only has default destructor, i.e. I don't declare its destructor at all, the exception does not occur. Regardless of whether the destructor is virtual or not. Both in debug and release build.

P。 。

推荐答案

这是未定义的行为调用 delete 使用 new [] 创建的指针。基本问题是当你调用 new [] 它需要分配额外的空间来存储数组中的元素数量,这样当你调用 delete [] 它知道要销毁的元素数量。

It is undefined behavior to call delete on a pointer created with new[]. The basic issue is that when you call new[] it needs to allocate extra space to store the number of elements in the array, so that when you call delete [] it knows how many elements to destroy.

除了实际对象所需的空间之外,库还将为管理数据分配空间。然后它将执行所有初始化并返回指向第一个元素的指针,该指针与从操作系统检索的内存块不匹配。

The library will allocate space for the management data in addition to the needed space for the real objects. It will then perform all initialization and return a pointer to the first element, which is not aligned with the block of memory retrieved from the OS.

[header][element1,element2...]
^       ^
|       \_ pointer returned by new[]
|
\_ pointer returned by the allocator

另一方面, new delete 不要存储任何额外的信息。

On the other hand, new and delete don't store any extra information.

当调用 delete [] 时,它将指针移回,读取计数,调用析构函数和释放原来的指针。当调用delete时,它会为单个对象调用析构函数,并将指针传递回分配器。如果通过调用 new [] 创建指针,则返回分配器的指针不是分配的同一个指针并且重新分配失败。

When you call delete[] it moves the pointer back, reads the count, calls the destructors and deallocates using the original pointer. When you call delete, it calls the destructor for the single object and passes the pointer back to the allocator. If the pointer was created through a call to new[], then the pointer that is returned to the allocator is not the same pointer that was allocated and the deallocation fails.

这篇关于为什么在类对象数组上调用delete而不是delete []会导致堆损坏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆