C++内存管理

在C++中内存主要分为5个存储区域:

  • 栈区:局部变量,函数参数等存储在该区域,栈区由编译器自动分配和释放,内存空间是连续的,但是栈的内存空间有限。

  • 堆区:需要程序员手动分配和释放,属于动态分配方式。内存空间几乎没有限制,内存空间不连续,因此会产生内存碎片。操作系统有一个记录空间内存的链表,当收到内存申请时遍历链表,找到第一个空间大于申请空间的堆节点,将该节点分配给程序,并将该节点从链表中删除。一般,系统会在该内存空间的首地址处记录本次分配的内存大小,用于delete释放该内存空间。

  • 全局/静态存储区:全局变量,静态变量分配到该区域,生命周期与程序保持一致,程序结束时自动释放。

  • 文字常量区:存放常量,而且不允许修改,程序结束后由系统释放。

  • 程序代码区:存放程序的二进制代码

静态区,常量区也可以称为数据段,文字常量区和程序代码区合并为代码段。

使用存储区的三种方式:

1.静态存储区
全局变量,静态变量以及静态类成员存储在该区域,在编译期间就进行分配,生存周期到程序结束。存储在该区域的对象只初始化一次,并且在程序运行期间地址固定不变。
2.自动存储区
局部变量,函数参数等存储在该区,由编译器自动分配和释放。
3.自由存储区
由程序员手动分配和释放内存(new,delete)

堆和栈的区别:

  1. 空间大小
    栈的内存空间是连续的,空间大小通常是系统预先规定好的,即栈顶地址空间和最大空间是确定的;而堆的内存空间是不连续的,由一个记录空间的链表负责管理,因此内存空间几乎没有限制,在32位系统下,内存空间大小可达到4G。

  2. 管理方式
    栈有编译器自动分配和释放,而堆需要程序员来手动分配和释放,若忘记delete,容易产生内存泄漏。

  3. 生长方向不同
    对于栈,他是向着内存地址减小的方向生长的,这就是为什么栈的内存空间是有限的;而堆是向着内存地址大的方向生长的。

  4. 碎片问题:
    由于栈的内存空间是连续的,先进后出的方式保证不会产生零碎的内存空间;而堆的分配方式是每次在空闲链表中遍历到第一个大于申请空间的节点,每次分配的空间大小一般不会正好等于申请的内存大小,频繁的new操作,势必会产生大量的空间碎片。

  5. 分配效率
    栈属于计算机系统提供的数据结构,计算机会在底层对栈提供支持,出栈进栈由专门的指令指向,因此效率较高。而堆是C/C++函数提供的,当申请空间时候,需要按照一定算法搜索足够大小的内存空间,当没有足够的空间是,还需要额外的处理,因此效率较低。

使用内存的几点注意事项:

  • 1.用new和malloc申请内存时,在使用前需要检查内存是否分配成功。
  • 2.使用内存之前要进行初始化
  • 3.在对内存进行操作时,防止越界,如内存操作要注意下标范围
  • 4.对于动态分配的内存,一定要手动释放,否则程序没运行一次就会丢失一部分内存,造成内存泄露。
  • 5.防止内存释放后继续使用他,主要由以下情况:
    a.函数的return语句写错了,注意不要返回指向“栈内存”的指针或者引用,因为该内存在函数体结束时就被自动销毁了
    b.使用free或者delete释放内存后,没有将指针置为NULL,导致产生“野指针”

“野指针”:野指针不是NULL指针,是指向“垃圾内存”的指针,人们一般不会错用NULL指针,因为使用if语句很容易判断,但是“野指针”很危险,if语句对他不起作用。

野指针的成因:
1.指针变脸没有被初始化,任何指针变量刚被创建时不会自动成为NULL指针,他的缺省值是随机的,他会乱指一气、所以,指针变量在创建的同时应当被初始化,要么让指针置为NULL,要么让他指向合法的内存。

2.指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。
3.指针操作超越了变量的作用范围,多发生在数组中的使用中

  • 6.指针的注意点:

a.指针指向常量存储区对象
char p=“abc”;
此时p指向的是一个字符串常量,不能对
p的内容进行写操作,如srtcpy(p,s)是错误的,因为p的内容为“abc”字符串常量,该数据存储在常量存储区,但可以对指针p进行操作,让其指向其他的内存空间。

b.资源泄漏
char *p=new char[3]; //分配三个字符空间,p指向该内存空间
p=“ab”; //此时p指向常量“ab”,而不再是new char分配的内存空间了,从而造成了资源泄漏
delete []p; //释放时报错

c.内存越界
char *p=new char[3]; //分配三个字符空间,p指向该内存空间
strcpy(p,“abcd”); //将abcd存处在分配的内存空间中,由于strlen(“abcd”)=4>3,越界
delete []p; //释放时出错

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值