内存管理--bss data txt数据段与stm32的ZI-data RW-data RO-data Code数据段的关系

目录

前沿

1 数据在内存中的位置

1.1 堆栈在内存中的位置

1.2 全局变量和局部变量在内存中的位置

1.2.1 全局变量在内存中的位置

1.2.2 局部变量在内存中的位置

1.3 static变量在内存中的位置

1.4 malloc赋值的变量存放在内存中的位置

1.5 代码在内存中的位置

2 ZI-data RW-data RO-data和Code数据段

2.1 各个数据段的含义

2.2 bss data和txt数据段和ZI-data RW-data RO-data和Code数据段的关系

2.3 各个数据段在内存中的位置

2.3 应用程序加载和执行图


前沿

        我们经常听人提起bss数据段,txt数据段,data数据段,但是我们不知道是什么意思,有些读者和博主一样,经常使用keil这个软件,所以只知道ZI-data数据段,RW-data数据段,RO-data数据段,Code数据段,那么他们存在什么样的关系呢,本小节带大家粗略的了解一下他们的关系,如果有错,请大家指出。

1 数据在内存中的位置

        要搞懂本节,我们需要了解数据在内存中的存储方式,我们最长听见的词语就是堆栈了,下面我们就从堆栈进行进行讲解。

1.1 堆栈在内存中的位置

        我们常说的堆栈,其实单指堆区,但是严格来说,堆区和栈区是分开的,堆区是需要malloc开辟空间的,然而栈区是存放局部变量的数据区,是由系统自动分配(大小由用户定义)。

        我们使用最多的就是栈区,栈区的生长方式是向上生长,后面的小节为大家详细的讲解何为向上生长。

注意:堆区和栈区是存放在RAM空间的

1.2 全局变量和局部变量在内存中的位置

1.2.1 全局变量在内存中的位置

        全局变量又分为初始化为非零的全局变量、没有初始化或初始化为0的全局变量和const修饰的全局变量,他们在内存中的方式也是不同的。

  • 初始化为非零的全局变量

        初始化为非零的全局变量存储在ROM空间,当程序运行的时候,会自动的加载到RAM空间。

  • 没有初始化或初始化为0的全局变量

        此类变量因为没有赋值(默认全局变量初始值为0),所以不必存放在ROM空间,所以此类变量存放在RAM空间

  • const修饰的全局变量

        const修饰的全局变量为只读变量,也叫常量,它存放在ROM空间。

注意:char *p = "1234"定义的字符串常量也存在ROM空间

1.2.2 局部变量在内存中的位置

        局部变量的初始值不固定,编译器不同初始值也存在一定的差异,所以使用局部变量的时候,需要给它赋值,它存放在栈区,也就是RAM空间。

1.3 static变量在内存中的位置

        static修饰的变量分为全局变量和局部变量。

  • 全局变量表示只能在当前文件中使用,不能被《extern》关键词修饰到其它文件中使用。
  • 局部变量默认初始值为0,并且不会被函数的生命周期影响,也就是函数执行完成,此类变量的值不会被改变,它存放在ROM空间

1.4 malloc赋值的变量存放在内存中的位置

        mallco修饰的变量存放在堆区,也就是RAM空间

1.5 代码在内存中的位置

        代码,就是可执行的程序,它根据需求的不同存放的位置也有所不同,但是一般是存放在ROM空间的

2 ZI-data RW-data RO-data和Code数据段

        我们在使用keil第一次编译或者重新编译程序的时候,《Build Output》窗口会显示《Program Size: Code=8180 RO-data=880 RW-data=296 ZI-data=2176  》等信息,由于现在的单片机的ROM(FLASH)和RAM都比较大(相较于传统单片机),一般的程序不必考虑内存的问题,即使存在内存问题,编译器也会给你报错,所以这个就会导致很多现代的工程师很少关注这个问题,但是如果你对内存很敏感,比如你需要规定你的程序大小不能超过1Kbyte,或者不能使用超过250byte的RAM空间,查看这里的信息就显得十分的有用了。

2.1 各个数据段的含义

Code:代码域,指的是编译器生成的及其指令,这些内容被存储在ROM区。

RO-data(Read Only Data):只读数据域,指的是程序中用到的只读数据,这些数据被存储在ROM区,并且程序不能修改其内容。例如C语言中的关键词const定义的变量就是典型的RO-data。

RW-data(Read Write Data):可读可写数据域,指的是初始值为“非零”的可读写数据,程序运行之前这些数据被存储在ROM区,这些数据具有非零的初始值,程序运行的时候被加载到RAM区,并且常驻于RAM区。应用程序能够修改其内容。例如C语言中定义的赋值不为0的全局变量就是典型的RW-data。

注意:关键词static定义的变量虽然默认值为0,但是也存在RW-data中。

ZI-data(Zero Initialize Data):初始值为0的数据域,指的是初始化为0值的可读可写数据域。它与RW-data的区别是这些数据一直存在RAM区,并且是在程序运行的时候才被加载到RAM区,且被赋予初始值0,而后续运行过程与RW-data的性质一致。例如C语言中定义的未赋值的全局变量或者赋值为0的全局变量(没有赋值的全局变量初始值默认为0)。

ZI-data的堆空间和栈空间:在C语言中,函数内部定义的局部变量属于栈空间,进入函数的时候向栈空间申请内存给局部变量,退出时释放局部变量,归返内存空间。而使用malloc动态分配的变量属于堆空间。在程序中的堆和栈空间都属于ZI-data区域,这些空间都会被初始化为0,编译器给出的ZI-data占用的空间值中包含了堆栈的大小(若程序没有使用malloc动态申请内存,编译器会优化堆空间,不会把堆空间计算在内)。

注意:局部变量的初始值为0是因为在程序运行的时候局部变量被赋予0值,但是当程序运行的时候,堆栈不停的交换数据,所以当程序运行到某个局部变量的时候,此局部变量的值就为留在堆栈的随机值,因此上学的时候所说的局部变量的值是随机值由此而来。

2.2 bss data和txt数据段和ZI-data RW-data RO-data和Code数据段的关系

程序组件

所属类别

机器代码指令

Code(txt)

常量

RO-data(data)

初始非0的全局变量

RW-data(data)

Static定义的变量

RW-data(data)

初始为0的全部变量

ZI-data(bss)

局部变量

ZI-data栈空间(bss)

使用malloc动态分配的空间

ZI-data堆空间(bss)

2.3 各个数据段在内存中的位置

        RAM和ROM区域存储的数据如下:

  • Total RO Size (Code + RO Data)
  • Total RW Size (RW Data + ZI Data)
  • Total ROM Size (Code + RO Data + RW Data)
  • Total RAM Size (ZI Data + RW Data)

        下图表示RAM区存储的数据结构。栈区向上生长是压栈的时候SP指针减寄存器的大小,出栈的时候SP指针加上寄存器的大小,这就是所谓的向上生长。

        下图是压栈时SP指针值的变化。

        下图是出栈时SP指针值的变化。

        整个流程称为SP的压栈和出栈,可以看出它压栈的时候,是从高地址往低地址进行压栈的,这种方式称为向上生长。

2.3 应用程序加载和执行图

       当我们编译下载程序到ARM-M系列单片机中的时候,我们的程序存放在ROM空间的位置如左图所示,依次为DATA(R0)(此处为中断向量表),Code,Data(RO),Data(RW),程序复位的时候,PC默认指向0x08000004位置(0x08000000存放的是栈顶值),在复位的同时,程序会把存放在ROM空间的Data(RW)值加载到RAM空间(为了提高执行效率)。

        BSS(ZI)数据段也就是Data(ZI)数据段,它根据编译器不同存放的位置有所差异,常见是不存放在ROM空间的。

  • 47
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

binhaoPro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值