《操作系统真象还原》——0.15 局部变量和函数参数为什么要放在栈中

简介: 局部变量,顾名思义其作用域属于局部,并不是像static那样属于全局性的。全局的变量,意味着谁都可以随时随地访问,所以其放在数据段中。而局部变量只是自己在用,放在数据段中纯属浪费空间,没有必要,故将其放在自己的栈中,随时可以清理,真正体现了局部的意义。

本节书摘来自异步社区《操作系统真象还原》一书中的第0章,第0.15节,作者:郑钢著,更多章节内容可以访问云栖社区“异步社区”公众号查看

0.15 局部变量和函数参数为什么要放在栈中

局部变量,顾名思义其作用域属于局部,并不是像static那样属于全局性的。全局的变量,意味着谁都可以随时随地访问,所以其放在数据段中。而局部变量只是自己在用,放在数据段中纯属浪费空间,没有必要,故将其放在自己的栈中,随时可以清理,真正体现了局部的意义。这个就是堆栈框架,提到了就说一点吧,栈由于是向下生长的,堆栈框架就是把esp指针提前加一个数,原esp指针到新esp指针之间的栈空间用来存储局部变量。解释一个概念,堆是程序运行过程中用于动态内存分配的内存空间,是操作系统为每个用户进程规划的,属于软件范畴。栈是处理器运行必备的内存空间,是硬件必需的,但又是由软件(操作系统)提供的。堆是堆,而堆栈就是栈,和堆没关系,只是都这么叫。栈和堆栈都是指的栈,在C程序的内存布局中,由于堆和栈的地址空间是接壤的,栈从高地址往低地址发展,堆是从低地址往高地址发展,堆和栈早晚会碰头,它们各自的大小取决于实际的使用情况,界限并不明朗,所以这可能是堆栈常放在一直称呼的原因吧。

函数参数为什么会放到栈区呢?第一也是其局部性导致的,只有这个函数用这个参数,何必将其放在数据段呢。第二,这是因为函数是在程序执行过程中调用的,属于动态的调用,编译时无法预测会何时调用及被调用的次数,函数的参数及返回值都需要内存来存储,如果是递归调用的话,参数及返回值需要的内存空间也就不确定了,这取决于递归的次数。也许这么说您也依然觉得费解,如果完全明白,需要了解一下编译原理,很多知识都是通过实践后才搞明白的。当然我不是说让您为了搞明白这个问题而去尝试写个编译器。

总之,在函数的编译阶段根本无法确定它会被调用几次,其参数和函数的返回地址也要内存来存储,所以也不知道其会需要多少内存。我想,即使神通广大的编译器设计者可以预测这些了,那提前准备好内存也是一种浪费,而且您想啊,在系统中可用内存紧缺的情况下,提前把内存分配给目前并不使用内存的进程(只因为要存储其函数参数),而眼前需要内存的程序若无内存可用,引用罗永浩老师的一句话:“我想不到比这个更伤感的事情了”所以编译器为了让世界更美好一些,选择将为函数参数动态分配内存,也就是在每次调用函数时才为它在栈中分配内存。

相关文章
操作系统实验五 基于内核栈切换的进程切换(哈工大李治军)(三)
操作系统实验五 基于内核栈切换的进程切换(哈工大李治军)(三)
239 0
操作系统实验五 基于内核栈切换的进程切换(哈工大李治军)(三)
|
4月前
|
关系型数据库 Unix Shell
File - os.tcsetpgrp(fd, pg)函数
`os.tcsetpgrp(fd, pg)` 函数在进行进程控制和信号管理时非常有用,但它涉及Unix底层的工作原理,因此使用时需具备相应知识,以确保正确和适用,并注意相关的权限和错误处理。
154 61
|
3月前
|
弹性计算 开发框架 .NET
阿里云服务器购买教程及云服务器地域、实例、操作系统、带宽等参数选择指南
对于初次购买阿里云服务器的用户来说,想使用阿里云服务器搭建网站或者运行APP、小程序等项目,第一步就是要先购买阿里云服务器,下面小编以图文形式给大家介绍一下阿里云服务器的购买流程,以及购买过程中如何云服务器地域、实例、带宽等关键配置和选择这些参数的一些注意事项,以供参考。
|
4月前
|
存储 程序员 API
【收藏】非API函数检测操作系统类型
【收藏】非API函数检测操作系统类型
|
8月前
|
Python
在Python中,利用`os模块`的`path.exists()`函数可判断文件是否存
【5月更文挑战第12天】在Python中,利用`os模块`的`path.exists()`函数可判断文件是否存在,该函数对路径进行检查,存在则返回True,不存在则返回False。示例代码展示了如何检查'example.txt'文件是否存在并相应打印消息。此外,`os.path.isfile()`用于确认路径是否为文件,仅当是文件时返回True,否则返回False,同样配以示例说明其用法。
307 2
|
存储
【OS Pintos】用户程序是如何工作的 | Pintos 运行原理 | 虚拟内存 | 页函数 | 系统调用
【OS Pintos】用户程序是如何工作的 | Pintos 运行原理 | 虚拟内存 | 页函数 | 系统调用
374 0
|
8月前
|
Python
深入探索Python中的os.listdir函数
探索Python `os.listdir()`函数,用于获取目录下文件和子目录列表。os模块提供操作系统接口,`listdir()`返回指定路径的文件名列表。基本用法是`os.listdir(path)`,默认为当前目录。通过递归调用可遍历目录树,结合`os.path`处理隐藏和特殊文件。注意异常处理,如`FileNotFoundError`。Python 3.5引入的`os.scandir()`更高效。了解更多详情,请参考官方文档。
175 3
|
8月前
|
Unix Python Windows
深入了解Python中的os.path.join函数
探索Python `os.path.join` 函数:用于跨平台拼接路径,自动处理分隔符,支持绝对/相对路径及特殊字符。了解其基本用法、异常处理和最佳实践,提升文件路径操作的可靠性与可移植性。查阅[Python官方文档](https://docs.python.org/3/library/os.path.html)获取更多详情。
456 0
|
Shell Linux Go
《Linux操作系统编程》第八章 Shell程序设计: shell 语言结构,包括测试、分支、循环、跳转、函数、语句组
《Linux操作系统编程》第八章 Shell程序设计: shell 语言结构,包括测试、分支、循环、跳转、函数、语句组
134 0
|
存储 监控 Linux
《Linux操作系统编程》 第六章 Linux中的进程监控: fork函数的使用,以及父子进程间的关系,掌握exec系列函数
《Linux操作系统编程》 第六章 Linux中的进程监控: fork函数的使用,以及父子进程间的关系,掌握exec系列函数
183 0