New和delete的原理

来源:互联网 发布:照片转油画软件 app 编辑:程序博客网 时间:2024/04/29 06:57
New和delete的原理

  当我们在程序中写下   new   和   delete   时,我们实际上调用的是   C++   语言内置的   new   operator   和   delete   operator.所谓语言内置就是说我们不能更改其含义,它的功能总是一致的。以   new   operator   为例,它总是先分配足够的内存,而后再调用相应的类型的构造函数初始化该内存。而   delete   operator   总是先调用该类型的析构函数,而后释放内存(图1)。我们能够施加影响力的事实上就是   new   operator   和   delete   operator   执行过程中分配和释放内存的方法。

  new   operator   为分配内存所调用的函数名字是   operator   new,其通常的形式是   void   *   operator   new(size_t   size);   其返回值类型是   void*,因为这个函数返回一个未经处理(raw)的指针,未初始化的内存。参数   size   确定分配多少内存,你能增加额外的参数重载函数   operator   new,但是第一个参数类型必须是   size_t.

  delete   operator   为释放内存所调用的函数名字是   operator   delete,其通常的形式是   void   operator   delete(void   *memoryToBeDeallocated);它释放传入的参数所指向的一片内存区。

  这里有一个问题,就是当我们调用   new   operator   分配内存时,有一个   size   参数表明需要分配多大的内存。但是当调用   delete   operator   时,却没有类似的参数,那么   delete   operator   如何能够知道需要释放该指针指向的内存块的大小呢?答案是:对于系统自有的数据类型,语言本身就能区分内存块的大小,而对于自定义数据类型(如我们自定义的类),则   operator   new   和   operator   delete   之间需要互相传递信息。

  当我们使用   operator   new   为一个自定义类型对象分配内存时,实际上我们得到的内存要比实际对象的内存大一些,这些内存除了要存储对象数据外,还需要记录这片内存的大小,此方法称为   cookie.这一点上的实现依据不同的编译器不同。(例如   MFC   选择在所分配内存的头部存储对象实际数据,而后面的部分存储边界标志和内存大小信息。g++   则采用在所分配内存的头   4   个自己存储相关信息,而后面的内存存储对象实际数据。)当我们使用   delete   operator   进行内存释放操作时,delete   operator   就可以根据这些信息正确的释放指针所指向的内存块。

  以上论述的是对于单个对象的内存分配/释放,当我们为数组分配/释放内存时,虽然我们仍然使用   new   operator   和   delete   operator,但是其内部行为却有不同:new   operator   调用了operator   new   的数组版的兄弟-   operator   new[],而后针对每一个数组成员调用构造函数。而   delete   operator   先对每一个数组成员调用析构函数,而后调用   operator   delete[]   来释放内存。需要注意的是,当我们创建或释放由自定义数据类型所构成的数组时,编译器为了能够标识出在   operator   delete[]   中所需释放的内存块的大小,也使用了编译器相关的   cookie   技术。 (千万要注意,使用了编译相关的cookie技术,我可是吃过亏的人了阿)

  综上所述,如果我们想检测内存泄漏,就必须对程序中的内存分配和释放情况进行记录和分析,也就是说我们需要重载   operator   new/operator   new[];operator   delete/operator   delete[]   四个全局函数,以截获我们所需检验的内存操作信息。
原创粉丝点击