您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

对于内存结构的简单理解

时间:2020-08-17 11:17:51  来源:  作者:

最近花了点时间读了《深入理解C指针》这本书,读完这本书后,对于之前嵌入式C语言开发中很多一知半解的地方豁然开朗。对于之前学习以及工作中,很多没有注意的问题,也有了更加深刻的理解和认识。今天就花点时间整理下这段时间读完这本书后的所学所得,也方便后续查看。

我们在开发C语言程序的时候,程序需要在编译器中编译后,才能在对应产品中运行。在程序运行的过程中,内存的分配一般分为以下几个部分:

  • 堆(heap)
  • 栈(stack)
  • BSS区
  • 数据区
  • 代码区

对于我们平时开发的C程序,加载到处理器的内存中运行,呈现出来的结构就大概分为以上五个区域。为了更好地理解,我们可以根据下面这张图去理解。

对于内存结构的简单理解

 

下面我们简单地对上述几个区域做一下介绍。首先从代码区开始。


代码区

我们需要了解的是,我们在使用C语言开发产品程序代码的时候,最终的开发好的程序是并不能直接在产品的处理器中直接运行的。而是需要经过编译器的编译,最终将我们的代码转换成CPU处理器所能够理解的机器指令,才能在CPU中正常运行。而代码区,我们可以简单地理解为我们编写好的程序(已经转换为机器指令的程序代码)存放的地方。CPU处理器会从这个地方取出机器指令去完成对应的操作,最终实现我们想让CPU所实现的功能(简单的算术运算,或者对应的硬件操作等)。

栈区

栈区,这个区域不需要我们去维护管理,在程序运行的过程中,会自动的分配和释放。可能有些人不太能理解这个区域是做什么用的,这里我们简单地做一下介绍。

我们在开发嵌入式C程序代码的过程中,经常会在定义一些函数,去完成特定的功能(例如:定义一个addfunc函数用于实现两个数的加法运算,或者说更加复杂的,定义一个函数来对一个链表进行查询操作),在这些函数中,我们不可避免地,会去定义一些局部变量(局部变量的概念就不在这里做介绍了,不理解的建议去过一遍谭浩强的C语言程序开发)。在程序运行的过程中,我们需要一个地方去存储我们定义的这些局部变量,调用函数时的参数值,返回值等,而这个地方就是栈。

栈区是处于不断变化的状态中,举个例子,当前,程序运行在main函数中,此时栈中存储的则是main函数中我们定义的一些局部变量。这个时候,假如我们在main函数中去调用其他函数,那么,栈中会自动进行出栈操作,然后再进行入栈操作,将我们调用的那个函数的相关的局部变量,函数参数,返回值等都压入到栈中。如下图所示:

对于内存结构的简单理解

 

最先开始,程序从main函数开始运行,在调用addfunc函数之前,栈中的存储内容可能是这样的。

对于内存结构的简单理解

 


对于内存结构的简单理解

 

而在调用了addfunc函数后,栈区的内容就会被自动地替换为addfunc函数中的局部变量等内容。在返回main函数后,又会自动进行出栈入栈操作。

对于内存结构的简单理解

 

我们在不断地调用函数的同时,也自动不断地进行入栈以及出栈的操作,也就是说,我们定义的局部变量,实际上是在内存上不是一直会存在的,可能会在某一次的入栈及出栈操作中被覆盖掉。举个例子,我们可以试着编译运行下面这段代码。

对于内存结构的简单理解

 

这里我们在main函数中定义了一个局部变量a和b,以及一个res变量。接着我们调用addfunc函数,先将a和b变量的值进行相加,然后存储到res变量中。最后输出结果。看到这里,如果对C语言有点基础的朋友,就知道这种做法是得不到我们想要的预期结果的。而这就是因为我们程序在运行过程中,栈区不断进行入栈出栈导致的。我们在main函数中定义了a,b和res后,调用addfunc函数,此时栈区会进行出栈以及入栈操作,在addfunc函数中,做完加法运算后,res变量的值存储在栈中某个地址中,但是在addfunc函数返回后,会被下一次出栈入栈操作给覆盖掉。因此我们得不到我们想要的结果。

堆区

上面介绍完栈区后,我们这里再简单说下堆区。其实堆区和栈区,指向的是同一片内存区域。不同的是,这两个区域在这一块内存区域的两头,随着程序的运行,根据需要,一个不断向下增长,一个不断向上增长。(如下图)这也是我们经常喜欢说“堆栈“,而不是将这两个地方单独说”栈区“或”堆区“的原因。

对于内存结构的简单理解

 

堆区不同于栈区的另一个地方,就是我们程序想要在堆上开辟内存使用,方法不同于栈。在C程序中,我们定义了一个局部变量并赋值,这个过程可以理解为我们在栈上开辟了一个空间来使用,而且我们不需要去理会这个空间后续的回收问题。但是在堆上开辟空间的方法则不同。我们可以调用malloc函数在堆上开辟我们所需要使用的内存空间。在最后这段空间使用完毕后,则需要我们再调用free函数来释放掉我们申请的这段空间。否则就会发生内存泄露问题。当内存泄露的次数多了,则可能出现堆栈溢出。简单的说,就是我们一直向系统索要内存空间来使用,却忘记了“归还“,系统内存空间是有限的,当系统内存空间不够程序运行使用时,则会导致堆栈溢出,程序再也无法正常运行。

BSS区

这个区域存放的是未初始化的全局变量和静态变量。

数据区

这个区域存放的是已初始化的全局变量和静态变量,以及常量等。如下图:

对于内存结构的简单理解

 

我们在main函数中,定义了a,b,c三个变量,a和b变量均保存去数据区中,而c是一个指针,是局部变量,存放的是“hello world”字符串的地址,而这个字符串则存在于数据区。如下图

对于内存结构的简单理解

 



Tags:内存结构   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
Oracle内存结构Oracle内存结构是Oracle数据库重要组成部分,是 oracle 数据库重要的信息缓存和共享区域,和Oracle后台进程一起组成Oracle实例。Oracle用户的所有操作都会在内存...【详细内容】
2021-03-19  Tags: 内存结构  点击:(194)  评论:(0)  加入收藏
最近花了点时间读了《深入理解C指针》这本书,读完这本书后,对于之前嵌入式C语言开发中很多一知半解的地方豁然开朗。对于之前学习以及工作中,很多没有注意的问题,也有了更加深刻...【详细内容】
2020-08-17  Tags: 内存结构  点击:(56)  评论:(0)  加入收藏
运行时数据区域Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。Java虚拟机所管理的内存包括如下几个部分: 程序计数器程序计数器是一块较...【详细内容】
2020-02-23  Tags: 内存结构  点击:(43)  评论:(0)  加入收藏
多朋友可能会有许多关于Innodb如何使用内存的问题。我这里将简单介绍一下innodb内存结构,然后以innodb启动时的分配情况做一个解释。 1、INNODB内存结构 1.1、聚集索引与非聚...【详细内容】
2019-11-04  Tags: 内存结构  点击:(145)  评论:(0)  加入收藏
内存是什么?内存对于用户来说就是一个字节数组,我们可以根据地址来访问到某个字节或者某些字节:很久之前的内存很久很久之前,一台机器上只放置一个程序,操作系统仅仅作为一个函...【详细内容】
2019-09-20  Tags: 内存结构  点击:(207)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的  程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条