您的位置:首页 > 编程语言 > C语言/C++

C++内存管理

2016-07-17 22:26 239 查看
1.内存分配方式总结

前言先说说内存的分配方式,分为堆,栈、全局/静态存储区、常量存储区、自由存储区

 1)栈。函数局部变量存储单元在栈上创建。因为局部变量的生存周期,在函数结束的时候,栈上存储单元被释放。

特点:由于运算符内置于处理器的指令集中,效率很高,分配的内存容量有限。

  2)堆。new创建的变量,分配的内存块。

特点:需要手动去释放变量的内存块。程序结束后,操作系统会自动回收。

  3)自由存储区。malloc分配的内存块

  特点:与堆相似,需要用free去释放。

  4)自由存储区。创建的全局变量和静态变量,全局变量分为初始化和未初始化,共同在一块内存区

特点:全局变量和静态变量

  5)常量存储区。存放常量

特点:不允许修改

2.堆与栈的区别之处

eg:
void f(){  int *p=new int[8]; 
} //分配了一块栈内存,意思是:在栈内存上存放一块堆内存的指针p

release rel(){
 delete[] p;} //释放申请的内存

区别之处:

1)管理方式不同。栈由编译器自动管理;堆由程序员手动释放,已发生内存泄漏。

2)空间大小不同。栈控件一般是1M;堆内存可以达到4G。也可以通过配置进行修改。

3)能否产生碎片不同。栈是线进后出的队列,内存不易产生碎片;堆频繁进行new和delete,造成空间不连续,易产生碎片,程序效率降低。

4)生长方向不同。栈向下,向内存地址减小的方向增长;堆向上,向着内存地址增加的方向。

5)分配方式不同。栈分为静态和动态分配,静态由编译器完成,动态由alloc函数分配,编译器释放;堆动态分配

6)分配效率不同。栈由于底层的支持,有专用寄存器存放栈地址,压栈和出栈有专门的指令执行,效率高;堆根据函数库的算法申请内存空间,效率低。

3.防止堆破碎的通用方法

从不同固定大小的内存块中分配不同类型的对象。对每个类重载new和delete提供这样的控制。

重载eg:

void *operator new(size_t size){
void *p=malloc(size); return p;}

void operator delete(void *p)
{ free p;}
//使用malloc()和free()来实现重载

使用对单个类的new和delete进行重载

class TestClass

{

public:

void *operator new(size_t size){
void *p=malloc(size); return p;}

void operator delete(void *p)
{ free p;
}

void *operator new[](size_t size){
void *p=malloc(size); return p;}

void operator delete(void *p)
{ free p;
}

}

4.解决内存出错的方法

1)内存分配未成功,却使用了它。

解决办法:使用内存之前检查指针是否为NULL。

使用assert(p!=NULL);如果使用malloc和new来申请内存,则使用if(p==NULL)或者if(p!=NULL)进行防错处理。

2)内存分配虽然成功,但尚未进行初始化就引用它。

解决办法:起因:一是没有初始化观念,二是误认为内存缺省初值为0。

一般去进行初始化为0。

3)内存分配成功并且进行了初始化,但操作越过了内存的边界

解决办法:注意“多1”或者“少1”的操作

4)忘记了释放内存,造成内存泄漏。

解决办法:(起因:函数每调用一次就丢失一块内存,程序会突然提示:内存耗尽)

malloc和free要配对使用;new和delete要配对使用

5)释放了内存却仍在使用它

解决办法:

情况一:调用关系复杂,不清楚某个对象是否释放了内存。需要重新设计数据结构,从根本上解决对象管理混乱局面

情况二:return语句写错。不要返回“栈内存”的“指针”或者“引用”,函数结束时被自动销毁

情况三:使用free和delete释放后,没有置NULL。导致产生野指针。

5.指针参数是如何传递内存的?

若要指针参数去申请内存,使用指针的指针

eg:void GetMemory2(char **p,int num)

{

*p=(char *)malloc(sizeof(char *)*num);

}

char *str=NULL;

调用GetMemory2(&str,100);
strcpy(str,"hello"); free(str);

6.有了malloc和free,为什么还要new/delete

malloc和free是C/C++语言的标准库函数,new/delete是c++的运算符。但是malloc和free如何满足动态对象的要求。

引入new进行完成动态内存分配和初始化工作,引入delete完成清理与释放内存工作的运算符delete。

7.既然new/delete完全覆盖了malloc/free,为何malloc和free没有被淘汰

因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。

8.内存耗尽该怎么办?

1)判断指针是否为NULL,如果是,则用return语句终止本函数。

2)判断指针是否为NULL,如果是,使用exit(1)终止整个程序的运行。

3)为new和malloc设置异常处理函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息