11 | 堆和栈:函数调用是如何影响到内存布局的?
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了函数调用对内存布局的影响,以及栈结构在函数调用管理中的重要性。通过比较嵌套调用、使用setTimeout和Promise的不同方式,阐述了它们在内存布局上的差异,以及这种差异对代码执行逻辑的影响。文章还介绍了函数特性和作用域机制,以及栈结构在管理函数调用关系中的自然优势。通过生动的比喻,读者可以更直观地理解栈结构的后进先出特点。此外,文章还探讨了栈和堆的区别,以及它们在内存管理中的作用。总的来说,本文通过深入浅出的方式,帮助读者理解了函数调用对内存布局的影响,以及栈结构在函数调用管理中的重要性。文章还提出了一个思考题,引发读者对代码执行过程中页面卡死的原因进行思考。
《图解 Google V8》,新⼈⾸单¥59
全部留言(35)
- 最新
- 精选
- 刘大夫这相当于在当前这一轮任务里不停地创建微任务,执行,创建,执行,创建……虽然不会爆栈,但也无法去执行下一个任务,主线程被卡在这里了,所以页面会卡死
作者回复: 理解的很透彻了 👍
2020-04-101051 - 3SpidersJS的事件机制有宏任务和微任务。 宏任务是setTimeout、requestAnimationFrame、用户输入事件(I/O)等,它是由浏览器的队列完成的,在浏览器的主进程中进行,页面不会卡死。 微任务,包括Promise、MutationObserver等,是在浏览器的主线程中执行的,主线程通过一个while循环,一直拉取微任务,这样的循环会不断创建栈,再销毁栈,所以不会爆栈,但是因为在主线程中执行,所以页面会卡死。
作者回复: 主线程通过一个while循环一直拉取微任务 这句话可以修改下:主线程在当前任务快要执行结束之前,检查微任务队列中是否存在微任务,如果有,那么那么那么当前任务会依次取出微任务队列中的微任务,并一一执行! 补充一点,微任务队列是属于当前宏任务的,所以一个宏任务中产生的微任务,只会放到它自己的微任务队列中!
2020-04-09318 - Geek_49d301没写过js代码,猜测js应该也有两个队列,一个微任务队列一个事件队列,然后微任务队列的优先级高于事件队列,由于微任务队列一直被占用导致后面事件队列永远无法执行直到卡死
作者回复: 微任务队列属于当前任务,也就是说,微任务队列中的微任务、一定会在当前正在执行的任务退出之前执行完毕!
2020-04-0926 - 冯剑请问下栈帧是一个逻辑内存还是物理内存?
作者回复: 程序使用了自己的进程空间,64位系统,每个程序的虚拟进程空间是2^64,实际上使用时,才会在物理内存中开辟空间! 所以可以说,栈空间都是程序的虚拟空间,使用的地址和实际内存中的地址是不一样的,中间还做了一层映射!
2020-04-0933 - 大力function foo() { return Promise.resolve().then(foo) } foo() 上述代码执行后其实还是会报错的。 在执行5-10分钟后,Chrome会报错: paused before potential out-of-memory crash 然后当前宏任务继续处于被挂起状态。
作者回复: 是的
2020-04-262 - 桃翁老师,我有一个疑惑哈,就是我看你图中这些变量是按照栈来存的,那么当访问先入栈的变量的时候岂不是要把后入栈的弹出去才能访问?但是我觉得肯定不会这么做,老师能解释下怎么访问栈底部的变量么?
作者回复: 不需要弹出来啊,比如栈帧指针地址是1000,那么变量x对应栈顶的偏移是16,那么变量x的内存位置就是1000-16(通常情况下,栈的方向是向下增长的)
2020-04-0932 - 奕Promise属于微任务会在当前事件循环执行,一直会占用主线程,导致页面无法进行渲染,所以导致页面卡死
作者回复: 会在当前的任务中重复执行,导致当前任务无法退出,阻塞消息队列中的其它任务的执行! 我把你这句中的/当前事件循环\修改了下
2020-04-091 - 王楚然思考题: 不知道对不对, 1. 不会栈溢出,是因为Promise类似setTimeout将foo放入了任务队列。 2. 会卡死,是因为,Promise会将foo放入微任务队列,该队列在每次事件循环中都需要清空才能进行下一次事件循环。对比的setTimeout是将foo放入宏任务队列,该队列每次事件循环只处理一个任务。
作者回复: 微任务并没有进消息队列,它只是当前任务的一个未完成部分.
2020-04-0921 - 嘉就我一个人理解错了么,那个f97和f92是不是反了 应该是ebp对应f92,esp对应f97
作者回复: 嗯 画错了,已经调整了
2020-04-272 - wuqilv"答案依然是“不能”,这主要是因为 main 函数也有它自己的栈帧指针,在执行 main 函数之前,我们还需恢复它的栈帧指针。如何恢复 main 函数的栈帧指针呢?通常的方法是在 main 函数中调用 add 函数时,CPU 会将当前 main 函数的栈顶指针保存在栈中," 这里前面说的是 main 函数栈帧, 后面就变成了main 函数的栈顶,看着有点迷糊。
作者回复: 我写错了,已经改正过来了🤧
2020-04-10