内存模型

内存模型:

程序运行时,操作系统会给它分配一段内存,用来存储程序和运行时产生的数据。这段内存有起始地址和结束地址,比如从0x1000到0x8000,起始地址时较小的那个地址(0x1000),结束地址时较大的那个地址(0x8000)。
内存模型

Haep(堆)

​ 在程序的运行过程中,对于动态的内存占用请求(比如新建对象),系统就会从预先分配好的那段内存中,划出一部分给用户,具体规则是从起始地址开始划分。举例来说,用户要求得到10个字节内存,那么从起始地址0x1000开始给他分配,一直分配到地址0x100A,如果再要求得到22个字节,那么就分配到0x1020。
这里写图片描述

这种因为用户主动请求而划分出来的内存区域叫做Heap(堆)。它由起始地址开始,从低位(地址)向高位(地址)增长。Heap的一个重要特点是不会自动消失,必须手动释放,或者由垃圾回收机制来回收。

Stack(栈)

除了Heap以外,其他的内存占用叫做Stack(栈)。简单的说,stack是由于函数临时运行而临时占用的内存区域。也就是说,在函数执行完毕后,会释放所有的内部变量,不再占用空间。
这里写图片描述

例子:

int man() {
  int a = 2;
  int b = 3;
}

系统开始执行main函数时,会为它在内存中建立一个帧(frame),所有main的内部变量(比如a和b)都保存在这个帧里面。main函数执行结束后,该帧就会被回收,释放所有的内部变量,不再占用空间。
这里写图片描述

如果函数调用了其他函数,会发生什么情况?

int main() {
  int a = 2;
  int b = 3;
  return add_a_and_b(a,b);
}

main函数内部调用了add_a_and_b函数。执行到这一行的时候,系统也会为add_a_and_b新建一个帧,用来存储它的内部变量。也就是说,此时同时存在两个帧:main和add_a_and_b。一般来说,调用栈有多少层,就有多少帧。
这里写图片描述

等到add_a_and_b运行结束,它的帧就会被回收,系统会回到函数main刚才中断执行的地方,继续向下执行。通过这种机制,就实现了函数的层层调用,并且每一层都能使用自己的本地变量。

​ 所有的帧都存放在Stack,由于帧时一层层叠加的,所以Stack叫做栈。生成新的栈,叫做入栈(push);帧的回收叫做出栈(pop)。stack的特点是,最晚入栈的帧最早出栈,因为最内层的函数调用,最先结束运行,这就叫做“后进先出”的数据结构。每一次函数执行结束,就自动释放一个帧,所有函数结束,整个stack就都释放掉了。
这里写图片描述

stack是由内存区域的结束地址开始,从高位(地址)向低位(地址)分配。比如,内存区域的结束地址是0x8000,第一帧假定是16字节,那么下一次分配的地址就会从0x7FF0开始;假定第二帧需要64字节,那么地址就会移动到0x7FB0。
这里写图片描述

heap和stack的区别:

​ stack的分配速度与存取速度非常快,仅次于寄存器,栈数据可以共享。如果在编译之前确切知道需要分配多少数据,且数据不大,可以使用堆。堆中存放new出来的东西(数组,对象等)。缺点是存在栈中的数据大小与生存周期必须是确定的,缺乏灵活性。栈被附加到一个线程,所以当线程退出时,栈被回收。

​ heap是在运行时动态的分配内存大小,生存周期也不必事先告诉编译器。如果不知道运行时需要多少数据,或者需要分配大量数据,可以使用堆。栈中存放局部变量。缺点是由于要在运行时动态的分配内存,存取速度比较慢。堆通常在应用程序启动时由运行时分配,并在应用程序(技术上处理)退出时回收。


本文转自阮一峰老师的个人网站,原文链接汇编语言入门教程

如有疏漏及疑问,欢迎提出探讨。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值