嵌入式Linux与物联网软件开发——C语言内核深度解析》一1.7 内存管理之栈(stack)

简介:

本节书摘来自异步社区《嵌入式Linux与物联网软件开发——C语言内核深度解析》一书中的第1章,第1.7节,作者朱有鹏 , 张先凤,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.7 内存管理之栈(stack)

1.7.1 什么是栈

我们常常听人说堆栈,但大家一定要明确区分:堆就是堆,栈就是栈。我们平常说的堆栈一般是指栈。那栈的本质是什么?栈是一种数据结构,C语言中使用栈来保存局部变量(注意,下文中不强调的情况下,局部变量均指非静态局部变量)。栈是被发明出来管理内存的,是一种维护内存的机制,这就是栈的本质。

1.7.2 栈管理内存的特点(小内存、自动化)

栈的特点是入口即出口,只有一个口,另一个口是堵死的。所以先进去的后出来,也就是先进后出,而与栈特点相对的就是先进先出,也就是队列。队列的特点是入口和出口都有,必须从入口进去,从出口出来,所以先进去的必须先出来,否则就堵住后面的。

先进后出FILO   first in last out      栈
 先进先出FIFO   first in first out     队列
AI 代码解读

为了大家更形象地理解,我们给出两张图。栈就好比往一个容器里面放东西,只有一个口,先放进去的只能后来拿出,后来放进去的,可以最先拿出。而队列就好比一列火车或者排着队列的军队。走在最前面的也是最早通过隧道的,先进先出。


4f62e81ca7a8a4c32e324dec28fa5ffe3e970572


053958af2b0fd8c0bbf5cdf8aa7d70b74d047c17

队列

1.7.3 栈的应用举例:局部变量和函数调用

C语言中的局部变量是用栈来实现的。

我们在C语言中定义一个局部变量时(int a),编译器会在栈中分配一段空间(4字节)给这个局部变量用。分配时栈顶指针会移动出4个字节空间给局部变量a用的意思就是,将这4字节的栈内存的内存地址和我们定义的局部变量名a关联起来,对应的栈操作为入栈,就是将数据存入变量a中。需要注意的是,这里栈指针的移动和内存分配是自动完成的,不需要程序参与。

然后等我们函数退出的时候,局部变量就会被释放。对应的操作是弹栈(出栈)。出栈时也是栈顶指针移动,将栈空间中与a关联的那4个字节空间释放,这个动作也是自动的,不需要人为干预。所以我们在写代码的时候,一定不要从被调函数返回一个局部变量的地址给主调函数,因为在函数执行完后局部变量就释放了,这个地址里面的内容有可能被新的内容填充。这时如果你在主调函数里面使用它,就很有可能造成数据错误。

除了保存局部变量,栈对于函数调用来说也是至关重要的,栈保存着函数调用所需的所有维护信息。我们都知道,函数调用时,程序跳到被调函数内部,执行完后返回当前位置接着执行。这就好比你去一个陌生的地方探险,我们的目的是去寻求刺激,但是我们最后还是希望可以平安回家。在旅行前就必须做一些准备(如多带水、带指南针,等等)。我们的函数在调用时,跳到被调函数之前也是要做诸多准备的。对于函数来说,最起码它要找到回家的路,也就是被调函数的下一行代码的地址(为返回做准备),以及当前相关的局部变量值、寄存器的值等重要信息。之所以保存这些信息是怕在被调函数运行时,由于子函数会用到与主调函数一样的寄存器,而造成主调函数正在使用的寄存器数据破坏,在函数返回时,栈里面的数据弹出,即使寄存器被用过也没关系,弹出数据会使寄存器里面的值覆盖为调用以前,从而复原调用以前的现场。这些值保存在哪里呢?就保存在栈里。在函数调用时,将这些东西压入栈,在被调函数执行完,栈再弹出这些值。

以栈方式管理内存,好处是方便,分配和最后回收都不用程序员操心,C语言(背后的运行时系统)会自动完成。

分析一个细节:在C语言中,定义局部变量时如果未初始化,则值是随机的。为什么?

定义局部变量,其实就是在栈中通过移动栈指针,来给程序提供一个内存空间和这个局部变量名绑定。因为这段内存空间在栈上,而栈内存是反复使用的(脏的,上次用完没清零的),所以说使用栈来实现的局部变量定义时如果不初始化,里面的值就是一个垃圾值。由此我们扩展一下,其实不仅仅是局部变量,所有的变量在定义时只是在内存中分配一块空间,并没有对这块空间进行任何的初始化。如果这块内存以前被用过,里面的数据还在,那它对于我们来说是没有任何意义的垃圾值。而且有时候这些数据会对我们的编程造成错误。所以我们一定要初始化变量,也就是用新的、有用的数据覆盖掉以前的数据。可能你会有个问题,那些以前用过的内存经过操作系统回收后,为什么里面还有数据。其实操作系统仅仅是回收这些内存,告诉其他程序可以用了,但并不删除这些内存里面的数据。

C语言通过一个小手段来实现局部变量的初始化。

int a = 15;    // 局部变量定义时初始化
AI 代码解读

C语言编译器会自动把这行转成:

int a;         // 局部变量定义
  a = 15;        // 普通的赋值语句
AI 代码解读

1.7.4 栈的约束(预定栈大小不灵活,怕溢出)

首先,栈是有大小的。而且栈的大小是可以设置的,只是栈内存大小不好选择。如果太小怕溢出,太大怕浪费内存(这个缺点有点像数组)。

其次,栈的溢出危害很大,一定要避免。所以,在C语言中定义局部变量时不能定义太多或者太大(如不能定义局部变量时int a[10000];使用递归来解决问题时一定要注意递归收敛)。

相关实践学习
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
目录
打赏
0
0
0
0
1884
分享
相关文章
|
1月前
|
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
87 26
|
1月前
|
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
222 15
阿里云服务器实例选购指南:经济型、通用算力型、计算型、通用型、内存型性能与适用场景解析
当我们在通过阿里云的活动页面挑选云服务器时,相同配置的云服务器通常会有多种不同的实例供我们选择,并且它们之间的价格差异较为明显。这是因为不同实例规格所采用的处理器存在差异,其底层架构也各不相同,比如常见的X86计算架构和Arm计算架构。正因如此,不同实例的云服务器在性能表现以及适用场景方面都各有特点。为了帮助大家在众多实例中做出更合适的选择,本文将针对阿里云服务器的经济型、通用算力型、计算型、通用型和内存型实例,介绍它们的性能特性以及对应的使用场景,以供大家参考和选择。
自学esb32烧录进军物联网和嵌入式
自学esb32烧录进军物联网和嵌入式
|
6月前
|
java设置栈内存大小
在Java应用中合理设置栈内存大小是确保程序稳定性和性能的重要措施。通过JVM参数 `-Xss`,可以灵活调整栈内存大小,以适应不同的应用场景。本文介绍了设置栈内存大小的方法、应用场景和注意事项,希望能帮助开发者更好地管理Java应用的内存资源。
309 4
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
在C语言中,内存布局是程序运行时非常重要的概念。内存布局直接影响程序的性能、稳定性和安全性。理解C程序的内存布局,有助于编写更高效和可靠的代码。本文将详细介绍C程序的内存布局,包括代码段、数据段、堆、栈等部分,并提供相关的示例和应用。
247 5
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
212 5
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
211 6
Java内存管理深度解析####
本文深入探讨了Java虚拟机(JVM)中的内存分配与垃圾回收机制,揭示了其高效管理内存的奥秘。文章首先概述了JVM内存模型,随后详细阐述了堆、栈、方法区等关键区域的作用及管理策略。在垃圾回收部分,重点介绍了标记-清除、复制算法、标记-整理等多种回收算法的工作原理及其适用场景,并通过实际案例分析了不同GC策略对应用性能的影响。对于开发者而言,理解这些原理有助于编写出更加高效、稳定的Java应用程序。 ####
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。

物联网

+关注

相关产品

  • 物联网平台
  • 推荐镜像

    更多
  • DNS
  • AI助理

    你好,我是AI助理

    可以解答问题、推荐解决方案等

    登录插画

    登录以查看您的控制台资源

    管理云资源
    状态一览
    快捷访问