关于delete,delete [],operator delete()等 [英] About delete, delete[], operator delete(), etc

查看:397
本文介绍了关于delete,delete [],operator delete()等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能的重复项:

如何删除[]知道操作数数组操作数数组的大小?

(POD)释放内存:delete []等于删除?


据我所知,以下

  class A {}; 
A * a = new A;
//
delete A; code

$ c>(全局的,或由A提供的专门的)分配正确的内存量,然后调用A的构造函数。当 delete 被调用,将首先调用A的析构函数,然后调用 operator delete()来释放正确的内存量。



当我在TC ++ PL中读取时,这个正确的内存量是这样确定的:


要释放由new分配的空间,delete和delete []必须能够确定分配的对象的大小。这意味着使用new的标准实现分配的对象将占用比静态对象稍多的空间。通常,一个词用于保存对象的大小。


这很有意义。但是这个词存储在哪里可以通过 delete 访问?就在新指针指向的地址之前?因此 delete 可以通过访问 a-sizeof< void *> 获得要删除的大小?



你能澄清一下吗?



我认为这个答案可以帮助我理解 delete [] 工程。我知道 new [] 将如何工作, delete [] 将首先调用析构函数的数组和解除所有这些内存...



但是如何 delete []

解决方案

感谢您的帮助。



大多数运行时都会在返回的内存之前存储内存大小((BYTE *)p- sizeof(size_t)),但还有其他的选择。在我自己的内存管理器(是的,我写这种东西),我有一个更复杂的数据结构(使用指向链表,校验和...)之前返回的内存。



除了已分配内存的大小之外,new []还将存储实例的数量它知道有多少析构函数需要调用。这通常超出了内存管理器的范围,通常由C ++运行时/编译器本身处理。但是,这个数量的实例存储在哪里取决于编译器,虽然在实践中,我希望这个存储在返回的内存之前(以及内存管理器存储的任何数据之后)。



编辑:
以下小实用程序显示在分配的内存之前的内存布局:

  #include< iostream> 

typedef unsigned char Byte;

class X
{
public:
X():m_value(1){}
〜X(){m_value = 0;}
private:
int m_value;
};

void print(Byte * p,int offset)
{
printf(%at%d:0x%x(%d)\\\
,offset,p [offset]偏移]);
}

void main()
{
X * x = new X [10];

std: :cout<<x地址:<< x<< std :: endl;
std :: cout<<sizeof(X): (p,-1);
print(p,-1); print(p,-1);(b) -2);
print(p,-3);
print(p,-4);
print(p, - 5);
print(p,-6);
print(p,-7);
print(p,-8);
print(p,-9);
print(p,-10);

X * y = new X;
std :: cout<< Address of y:<< y < std :: endl;

p =(Byte *)y;
print(p,-1);
print(p,-2);
print(p,-3);
print(p,-4);
print(p,-5);
print(p,-6);
print(p,-7);
print(p,-8);
print(p,-9);
print(p,-10);运行这个提供了以下输出(在Visual Studio 2005上):



  x的地址:00481DE4 
sizeof(X):4
-1处的值:0x0 b $ b -2处的值:0x0(0)
-3处的值:0x0(0)
-4:0xa处的值(10)
-5处的值:0xc )
-6处的值:0x0(0)
-7处的值:0x2f(47)
-8处的值:0x8(8)
处于-9:0x2f的值(47)
-10处的值:0x98(152)
y的地址:00481E70
-1处的值:0xc(12)
-2处的值:0x0 )
-3处的值:0x2f(47)
-4处的值:0x8(8)
-5处的值:0x2a(42)
处于-6:0x98的值(152)
-7处的值:0xf8(248)
-8处的值:0xb0(176)
-9处的值:0x0(0)
处于-10的值:0x48(72)

你可以清楚地看到,在第一种情况数组),有4个字节用于指示元素的数目(0,0,0,10,其使值10在一起)。



在第二种情况,这些字节被省略,我们看到与第一种情况相同的模式(12,0,47,8)。我不知道Visual C ++在哪里存储分配的字节数,但它证明了元素的数量确实存储在返回的指针之前(在Visual Studio 2005中)。


Possible Duplicates:
How does delete[] “know” the size of the operand array?
( POD )freeing memory : is delete[] equal to delete ?

As I understand, the following

class A {};
A* a = new A;
//
delete A;

will result first in a call to operator new() (the global one, or a specialized one provided by A) to allocate the right amount of memory and then to a call to the constructor of A. And when delete is called, is will first call the destructor of A, and then call operator delete() to deallocate the "right amount of memory".

As I read in TC++PL, this "right amount of memory" is determined like that:

To deallocate space allocated by new, delete and delete[] must be able to determine the size of the object allocated. This implies that an object allocated using the standard implementation of new will occupy slightly more space than a static object. Typically, one word is used to hold the object's size.

This makes sense. But where is this word stored to be accessible by delete ? Just before the address pointed by the new pointer ? So that delete can obtain the size to be deleted by accessing a-sizeof<void*> ?

Can you clarify this ?

I think the answer to that may help me to understand how delete [] works. I understand how new [] will work, and that delete [] will first call the destructors for "all the objects of the array" and the deallocate all this memory...

But how can delete [] know the size of the array ?

Thanks for your helpful answers !

解决方案

It all depends on the implementation.

Most run-times will indeed store the memory size just before the returned memory ((BYTE *)p-sizeof(size_t)) but there are other alternatives. In my own memory manager (yes, I write this kind of stuff), I have a more complex data structure (using pointers to linked lists, checksums, ...) before the returned memory. It is actually up to the memory manager to decide where to store this information.

Besides the size of the allocated memory, new[] will also store the number of instances so it knows how many destructors to call. This is normally beyond the scope of the memory manager, and is normally handled by the C++ runtime/compiler itself. But again, where this number of instances is stored depends on the compiler, although in practice I would expect this to be stored just before the returned memory (and just after any data stored by the memory manager.

EDIT: The following small utility shows the memory layout before the allocated memory:

#include <iostream>

typedef unsigned char Byte;

class X
   {
   public:
      X() : m_value(1) {}
      ~X() {m_value = 0;}
   private:
      int m_value;
   };

void print(Byte *p,int offset)
{
printf ("Value at %d: 0x%x (%d)\n", offset, p[offset], p[offset]);
}

void main()
{
X *x = new X[10];

std::cout << "Address of x: " << x << std::endl;
std::cout << "sizeof(X)   : " << sizeof(X) << std::endl;

Byte *p = (Byte *)x;
print(p,-1);
print(p,-2);
print(p,-3);
print(p,-4);
print(p,-5);
print(p,-6);
print(p,-7);
print(p,-8);
print(p,-9);
print(p,-10);

X *y = new X;
std::cout << "Address of y: " << y << std::endl;

p = (Byte *)y;
print(p,-1);
print(p,-2);
print(p,-3);
print(p,-4);
print(p,-5);
print(p,-6);
print(p,-7);
print(p,-8);
print(p,-9);
print(p,-10);
}

Running this gives the following output (on Visual Studio 2005):

Address of x: 00481DE4
sizeof(X)   : 4
Value at -1: 0x0 (0)
Value at -2: 0x0 (0)
Value at -3: 0x0 (0)
Value at -4: 0xa (10)
Value at -5: 0xc (12)
Value at -6: 0x0 (0)
Value at -7: 0x2f (47)
Value at -8: 0x8 (8)
Value at -9: 0x2f (47)
Value at -10: 0x98 (152)
Address of y: 00481E70
Value at -1: 0xc (12)
Value at -2: 0x0 (0)
Value at -3: 0x2f (47)
Value at -4: 0x8 (8)
Value at -5: 0x2a (42)
Value at -6: 0x98 (152)
Value at -7: 0xf8 (248)
Value at -8: 0xb0 (176)
Value at -9: 0x0 (0)
Value at -10: 0x48 (72)

You can clearly see that in the first case (the new[]'d array), that there are 4 bytes used to indicate the number of elements (0,0,0,10 which makes together the value 10).

In the second case, these bytes are omitted and we see the same pattern (12,0,47,8) as in the first case. I don't know exactly where Visual C++ stores the number of allocated bytes, but it proves that the number of elements is indeed stored before the returned pointer (in Visual Studio 2005).

这篇关于关于delete,delete [],operator delete()等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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