揭秘程序栈:你的代码在幕后是怎么运行的?

计算机科学中,许多概念和原理可能会让开发者感到头疼,比如程序栈。这个看似晦涩的概念,实对我们理解程序运行至关重要。本文将以通俗易懂的方式,带你深入理解程序栈的工作原理和优化策略。

一、为什么需要栈?

栈是一种特殊的数据结构,它只允许在一端(称为栈顶)进行操作,比如插入(压栈)和删除(弹栈)。程序栈主要解决了两个问题:多层函数嵌套返回的问题,以及一些参数、临时变量的资源管理。

1.1 多层函数嵌套返回的问题

想象一下,你正在玩一个益智游戏,每个关卡你都需要记住一些信息,比如道具位置、怪物数量等。你通过一个关卡后,进入下一个,再下一个……这时,你需要返回前几个关卡,你还记得每个关卡的信息吗?答案很可能是不记得。

函数调用就像这个游戏,每次调用一个函数,都会进入一个新的"关卡",需要记住一些信息,比如返回地址、参数、局部变量等。这就需要一种结构来保存这些信息,以便函数返回时可以正确恢复状态。程序栈就扮演了这个角色。

1.2 参数、临时变量的资源管理

程序在运行过程中,会产生很多临时变量和函数参数,这些数据在使用完毕后就不再需要。如果手动管理这些资源,不仅麻烦,而且容易出错。程序栈提供了一种自动管理这些资源的机制:当函数返回时,程序栈中保存的函数参数、局部变量等就会被自动销毁,相应的资源也会被回收。

二、栈的工作原理

2.1 在内存为程序创建栈:线程栈

我们知道CPU的时间片是分配在线程上的,也就是说程序的执行实际上是在线程中进行的,那么函数的调用自然也是在线程中处理的,所以本文提到的程序栈也是需要关联到具体线程的,关联到具体线程的程序栈称为线程栈。

线程栈是每个线程独立拥有的一块栈内存空间,用于存储这个线程所调用的函数的栈帧。每个线程都有自己的程序栈。这是因为每个线程都是独立运行的,它们之间需要隔离,不能互相干扰。所以,线程栈就是存储程序栈的物理空间,而程序栈则是在这个物理空间中实现函数调用的逻辑结构。

那么,为什么不把栈放在CPU的寄存器中呢?

首先,CPU寄存器的容量有限,而且寄存器的主要任务是执行计算,如果寄存器用来存储栈,那么就可能影响CPU的计算效率。其次,现代CPU因为缓存的使用,其访问内存的速度已经非常快,几乎可以和访问寄存器相媲美。此外,把栈放在寄存器中,可能会使CPU设计变得复杂,提高CPU的成本,同时也需要修改指令集和各种编译器,这会带来很高的应用成本。

那么,栈的大小是多少呢?在Windows系统中,线程栈的默认大小是1M,可以由编译器指定;在Linux系统中,线程栈的默认大小是8M,可以由操作系统环境设置。

2.2 压栈和出栈

每次函数调用时,都会在栈上为这个函数创建一个栈帧,这个过程称为压栈。栈帧包含了函数运行所需的所有信息,比如返回地址、参数、局部变量等。当函数运行结束后,这个栈帧就会被销毁,这个过程称为出栈。

在压栈和出栈的过程中,需要进行rbp(register base pointer,栈底指针)和rsp(register stack pointer,栈顶指针)的切换。rbp用来指向栈底,rsp用来指向栈顶。

栈帧(Stack Frame)就像一个小的“盒子”,用来存放这个函数的一些重要信息。

每个栈帧通常包含以下几部分内容:

  1. 函数的参数:当我们调用一个函数时,需要向它传递一些参数。这些参数就会被存放在栈帧中。
  2. 局部变量:在函数内部定义的变量是局部的,它们的生命周期只在函数执行期间,所以这些局部变量也会被存放在栈帧中。
  3. 返回地址:当函数执行完毕后,CPU需要知道接下来应该跳转到哪里继续执行,这个“跳转到哪里”就是返回地址,它也会被存放在栈帧中。
  4. 保存的寄存器值:在函数调用过程中,可能会改变一些寄存器的值,为了在函数返回后能恢复这些寄存器的原始值,需要将这些寄存器的原始值保存在栈帧中。

所以,程序栈就是由一连串的栈帧组成,每个栈帧中保存了函数执行所需要的所有信息。

2.3 为什么从高地址向低地址分配?

一般来说,栈是从高地址向低地址分配的,但这并不是绝对的。在不同的操作系统和处理器架构下,栈的分配方式可能会不同。在Linux/x86架构中,栈确实是从高地址向低地址分配的。这里说的是栈帧的分配方式,栈内的数据分配方向则由编译器决定。

三、栈的优化策略

3.1 函数内联

函数内联是一种优化策略,它可以减少函数调用的开销。如果一个函数只被调用一次,或者函数体非常小,那么在编译时,编译器可以把这个函数的代码直接插入到调用它的地方,这就是函数内联。

函数内联可以减少压栈和出栈的开销,但是如果滥用,可能会导致程序体积过大。因此,一般只对"叶子函数"(即没有调用其他函数的函数)进行内联。

3.2 避免栈溢出

栈溢出是一种常见的程序错误,主要有两个原因:无限递归和栈中非常占内存的变量。

无限递归就是函数自己调用自己,且没有适当的终止条件,导致函数调用层次无限增加,最终导致栈溢出。解决方法是设置适当的递归终止条件。

栈中非常占内存的变量,比如大数组,也可能导致栈溢出。解决方法是尽量避免在栈上分配大量内存,可以考虑使用动态内存分配。

四、总结

程序栈是程序运行的重要基础,它解决了函数调用和资源管理的问题。理解程序栈的工作原理,可以帮助我们更好地理解程序的运行过程,也有助于我们编写出更高效的代码。希望本文的内容,能帮助你对程序栈有更深入的理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/332616.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jupyter-Notebook无法创建ipynb文件

文章目录 概述排查问题恢复方法参考资料 概述 用户反馈在 Notebook 上无法创建 ipynb 文件,并且会返回以下的错误。 报错的信息是: Unexpected error while saving file: Untitled5.ipynb attempt to write a readonly database 排查问题 这个是一个比较新的问…

保姆版Vps安装灯塔(ARL)

因为灯塔的默认端口为5003,所以我们在安装之前就在防火墙里把我们的5003端口打开 打开端口步骤如下: 1.我们打开控制面板,在控制面板里点击 系统和安全 。如下图: 2.接着点击 Windows Defender防火墙,如下图: 3.再…

IPhone、IPad、安卓手机、平板以及鸿蒙系统使用惠普无线打印教程

演示机型:惠普M281fdw,测试可行机型:惠普M277,惠普M452、惠普M283 点击右上角图标。 点击WI-FI Direct 开,(如果WI-FI Direct关闭,请打开!) 记录打印机的wifi名称(SSID)和密码。 打开IPhone、I…

kotlin Kmp多平台模板生成

地址: Kotlin Multiplatform Wizard | JetBrains 可生成kotlin多个平台模板 https://terrakok.github.io/Compose-Multiplatform-Wizard/

冻结Prompt微调LM: PET(b) LM-BFF

PET-TC(B) paper b: 2020.9 It’s not just size that matters: Small language models are also few-shot learners. Prompt: 多字完形填空式人工Prompt Task:Text Classification Model: Albert-xxlarge-v2 Take Away: 支持多字的完形填空Prompt&a…

vue中父组件异步传值,渲染问题

vue中父组件异步传值&#xff0c;渲染问题 父组件异步传值&#xff0c;子组件渲染不出来。有如下两种解决方法&#xff1a; 1、用v-if解决&#xff0c;当父组件有数据才渲染 <Child v-if"dataList && dataList.length > 0" :data-list"dataLis…

09 STM32 - PWM

9.1 PWM简介 脉冲宽度调制(Pulse Width Modulation,简称PWM)&#xff0c;是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点&#xff0c;就是对脉冲宽度的控制。 9.2 PWM波原理 如下图所示&#xff0c;使用定时器定时&#xff0c;从0开始&#x…

抽象类(没有对象)之引用对象失败之谜

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 欢迎&#x1f64f;点赞&#x1f5e3;️评论&#x1f4e5;收藏&#x1f493;关注 &#x1f496;衷心的希…

第十二章 Spring Cloud Alibaba Sentinel

文章目录 前言1、简介1.1、基本概念 2、Sentinel控制台3、Sentinel开发流程3.1、 app-api消费端工程引进依赖3.1.1、yml新加配置&#xff08;跟nacos同级&#xff09; 3.2、定义资源3.3、定义规则3.3.1、流量控制3.3.2、流控模式3.3.3、流控效果3.3.4、熔断降级3.3.5、通过Naco…

基于springboot+vue的社区团购系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

腾讯云MPS为出海媒体企业助力

在如今互联网发达的时代&#xff0c;一个视频通过网络发布即可供给全球用户进行观看。其中视频媒体企业便其中的领头先锋&#xff0c;为了让创作者们以及全球各大用户的视频进行快速推广&#xff0c;出海则是不二之选。但是因为各地区域的不同&#xff0c;带宽的不同与网络的限…

【EI会议征稿通知】第四届工业制造与结构材料国际学术会议(IMSM 2024)

第四届工业制造与结构材料国际学术会议&#xff08;IMSM 2024&#xff09; 2024 4th International Conference on Industrial Manufacturing and Structural Materials&#xff08;IMSM 2024&#xff09; 第四届工业制造与结构材料国际学术会议&#xff08;IMSM 2024&#x…

WordPress怎么禁用文章和页面古腾堡块编辑器?如何恢复经典小工具?

现在下载WordPress最新版来搭建网站&#xff0c;默认的文章和页面编辑器&#xff0c;以及小工具都是使用古腾堡编辑器&#xff08;Gutenberg块编辑器&#xff09;。虽然有很多站长说这个编辑器很好用&#xff0c;但是仍然有很多站长用不习惯&#xff0c;觉得操作太难了&#xf…

Spring Boot自动配置原理

1.SpringBootApplication注解 springboot是基于spring的新型的轻量级框架&#xff0c;最厉害的地方当属**自动配置。**那我们就可以根据启动流程和相关原理来看看&#xff0c;如何实现传奇的自动配置 SpringBootApplication//标注在某个类上&#xff0c;表示这个类是SpringBo…

微软与沃达丰签订10年合作,提供Copilot等生成式AI服务

1月16日&#xff0c;微软在官网宣布&#xff0c;与全球最大电信公司之一沃达丰&#xff08;Vodafone&#xff09;签订10年合作协议&#xff0c;将为3亿多企业、消费者提供生成式AI、云和数字服务等。 通过此次合作&#xff0c;沃达丰将利用微软的Copilot等生成式AI来改变客户、…

基于麻雀优化算法SSA的CEEMDAN-BiLSTM-Attention的预测模型

往期精彩内容&#xff1a; 时序预测&#xff1a;LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较-CSDN博客 风速预测&#xff08;一&#xff09;数据集介绍和预处理-CSDN博客 风速预测&#xff08;二&#xff09;基于Pytorch的EMD-LSTM模型-CSDN博客 风速预测&#xff…

StarRocks 生成列:百倍提速半结构化数据分析

半结构化分析主要是指对 MAP&#xff0c;STRUCT&#xff0c;JSON&#xff0c;ARRAY 等复杂数据类型的查询分析。这些数据类型表达能力强&#xff0c;因此被广泛应用到 OLAP 分析的各种场景中&#xff0c;但由于其实现的复杂性&#xff0c;对这些复杂类型分析将会比一般简单类型…

align-item 和 align-content

align-item 和 align-content flex 布局中的 align-items 和 align-content 属性都用于垂直对齐 flex 容器内的项目&#xff0c;但它们适用于不同的情况&#xff1a; align-items: 这个属性用于在交叉轴上对齐单行内的 flex 项目。当你有一个 flex 容器&#xff0c;并且里面的…

【开源】基于JAVA的软件学院思政案例库系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统管理员2.2 普通教师 三、系统展示四、核心代码4.1 查询思政案例4.2 审核思政案例4.3 查询思政课程4.4 思政案例点赞4.5 新增思政案例评语 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的软件学…

第16章_网络编程拓展练习(TCP编程,UDP编程)

文章目录 第16章_网络编程拓展练习TCP编程1、学生与老师交互2、查询单词3、拓展&#xff1a;查询单词4、图片上传5、拓展&#xff1a;图片上传6、多个客户端上传文件7、群聊 UDP编程8、群发消息 第16章_网络编程拓展练习 TCP编程 1、学生与老师交互 案例&#xff1a;客户端模…