C++内存模型

需要先明确一点是,内存模型中涉及到的地址都是32位系统下的,其中涉及到的内存都是虚拟内存和虚拟地址,之所以会出现虚拟,是系统为了能更好、更高效管理使用内存,对实际物理内存进行了映射,使得应用程序的执行不用考虑物理内存的硬件细节。

1、栈内存

(1)因为是按照“先进后出”原则来操作的,此为栈。系统会自动申请栈内存并判断,空间不够的话会提示栈溢出。

(2)栈的全称是“运行时栈”,在程序运行过程中每当有一个函数被调用,会从栈中分配一帧内存,来存放局部变量,包括所有的形参,当函数调用结束,该内存就会立即被释放掉。

(3)栈也能实现函数的嵌套调用与返回,可以保存切换函数时的当前代码地址和寄存器值,此过程便是“保存现场”,被嵌套的函数执行完毕后,程序从之前保存的代码地址接着往下运行,称为“恢复现场”。

(4)栈的大小有限,不同系统栈的大小各有不同,如果嵌套函数过多,占用栈内存不断增大,超过最大值可能会产生“栈溢出”导致程序奔溃。

2、堆内存

(1)堆内存经常被称为自由区,因为这个区域内的大小定义和释放量都是由用户自己决定。

(2)堆的全称为“运行时堆”,因为随着进程的运行,堆的大小都在改变。

(3)堆内存的生命周期从malloc()/calloc()/realloc()开始,到free()/delete()结束,申请内存与释放内存的时机可以由用户自定义。如果结束时用户不释放,则有可能由系统进行回收。

(4)堆是没有大小限制的,最大值由物理内存决定,唯一限制的是虚拟内存的大小,当虚拟内存的内存池用完的时候,系统会从磁盘开始切割内存出来用,但是切割出来的内存速度很慢,这个切割的大小可以在系统的内存设置中配置。

3、数据段

数据段分为.bss、.data、.rodata三个区域,结束时由系统进行释放

(1).bss

 存放还未初始化的静态变量(所有全局变量以及static局部变量),并统一初始化为0。

(2).data

存放已经初始化的静态变量

(3).rodata

存放只读变量,也就是常量。

4、代码段

(1).test

存放用户定义的所有函数代码。

(2).init

存放系统给每一个可执行程序自动添加的初始化代码,该代码只执行一遍,包括环境变量的配置、命令行参数组织和传递等,这部分数据则被放在了栈底,即紧挨着内核的地方。

如果环境变量被修改,修改后的新的环境变量会被复制到堆中。

如果用户自定义的函数只需要执行一遍的话,也可以挡在.init段中。

5、为什么放在.bss中的为初始化静态变量还需要被初始化为0?

这么做的目的是为了节省磁盘空间,因为还未初始化的静态变量都被统一赋值成了0,所以就不用再专门开辟新的内存去存放变量的值了。

6、为什么内核、内存、堆栈大小是如何确定的?

(1)内核大小:0xC000 0000~0xffff fffff =====>0x3FFF FFFF ========>1073741823Byte=========>1G;

(2)在32位系统上,理论上内存大小2^32 = 4G;

(3)因此理论上堆的最大申请空间为3G,可实际上少于3G,因为还有栈区,数据段和代码段;

7、内存碎片问题?

频繁的申请和释放内存,必然导致一些没有被利用的碎片内存出现,这样造成的后果就是一旦需要一片连续内存的时候,即使内存总量足够,也无法满足连续的要求,这就是内存碎片问题。

8、内存泄漏

用户申请使用了一块内存,用完却没有释放,那么这块内存就谁也用不了,这就是内存泄漏。

9、内存溢出

内存泄漏如果一直发生,那么内存被占用会越来越多,超过内存总大小就奔溃了,这就是内存溢出。

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值