阿信@SYSU

求知若渴,求智若愚
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C++内存管理机制

Posted on 2012-04-26 11:53  阿信@SYSU  阅读(964)  评论(0)    收藏  举报

 

  内存分配方式

  在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。

  栈,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

  堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

  自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。

  全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。

  常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。

  示例一

1 void func()
2  {
3        int* p=new int[5];
4        delete []p;
5  }

  说明:func()与栈有关,new与堆有关。该语句表示在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中。

 

  堆与栈的区别

区别
管理方式 编译器自动管理 程序员手动管理
空间大小 有限制 一般无限制
生长方向 向着内存地址减小的方向增长 向着内存地址增加的方向
分配方式

局部变量是由编译器静态分配;

动态分配是由alloca函数进行,最后由编译器自动释放;

动态分配
效率

高。栈是机器系统提供的数据结构,计算机在底层对栈提供支持,

分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行

低。堆则是C/C++函数库提供的,它的机制是很复杂的,为了分配一块内存,

库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间,

碎片问题

先进后出,不产生碎片

频繁的new/delete势必会造成内存空间的不连续,造成大量碎片

 

  内存分配规则

  【规则1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。

  【规则2】不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

  【规则3】避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。

  【规则4】动态内存的申请与释放必须配对,防止内存泄漏。

  【规则5】用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。

“野指针”不是NULL指针,是指向“垃圾”内存的指针。产生原因:指针变量没有被初始化;指针p被free或者delete之后,没有置为NULL;指针操作超越了变量的作用域范围。

 

  malloc/free和new/delete的区别

  malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。

  对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。

  因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。

  malloc/free和new/delete用法

//malloc/free原型
void * malloc(size_t size);
void free(void * memblock);

int *p1 = (int*) malloc(sizeof(int)*length);
int *p2 = new int[length];
free(p1);
delete []p2;

  说明:

  指针p1的类型以及它所指的内存的容量事先都是知道的,语句free(p)能正确地释放内存;

  new内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言,new在创建动态对象的同时完成了初始化工作。如果对象有多个构造函数,那么new的语句也可以有多种形式。