CODE,RO-DATA,RW-DATA,ZI-DATA+单片机程序执行流程+堆(heap)和栈(stack)==精华详解

一.CODE,RO-DATA,RW-DATA,ZI-DATA

    CODE:顾名思义,就是代码,指程序中代码即函数体的大小;

    RO-DATA:RO就是只读的意思,程序中只读的变量(也就是带Const的)和已初始化的字符串等

    RW-DATA:特指已初始化的可读可写全局/静态变量

    ZI-DATA:未初始化的可读可写全局/静态变量,注意初始化为0也算做未初始化,Stack_Size(栈大小)也会被算入这里面

    CODE+RO-DATA+RW-DATA=程序大小=程序占用的FLASH空间=BIN文件大小,为什么ZI-DATA不算?因为对于未初始化的变量BIN文件里面只需要两句话描述一下就可以了,大概就是记录下ZI-DATA的大小就好,程序运行时直接在RAM中开辟一个相应大小的空间;

    RW-DATA+ZI-DATA+堆+栈大小(Stack_Size)=程序占用的RAM大小,但是如果程序没有使用到堆区(没有动态申请内存),则将堆忽略(对于MDK来说,因为MDK会将其忽略)。

二.堆和栈

    堆是用来给程序动态申请内存用的,栈存放局部变量、当前执行的代码和函数调用现场的保存;

    所以若程序没有动态申请内存,则不用管堆,若是有动态申请内存则注意设置下Heap_Size,Heap_Size要大于程序动态申请的内存大小。

    栈的大小不太好确定,因为栈所需的空间的变化因素很多,当前执行的函数的局部变量多少、函数代码量大小、函数嵌套调用层级数等都会影响,所以最好尽量设置得大一点。

   

四.测试方式/流程

    1.定义一个全局变量,使用printf打印出它的内存地址,发现就是正正好的0x20000000,说明全局/静态变量就是从内存首地址开始的

    2.再定义一个全局变量,将这两个变量的地址都打印出来(都是无符号8位的变量),发现其地址就是0x20000001

    3.定义一个只读变量,打印出其地址,发现其地址是以0x08000000开头的,也就是处于flash区域,说明RO-DATA的确不占用RAM空间

    4.定义一个局部变量,打印出其地址,发现是以0x20000000开头的,说明局部变量是处于栈区的

    5.定义一个静态变量,打印出其地址,发现为0x20000002,说明静态变量跟全局变量在一块

    6.再定义一个局部变量,打印出其地址,发现其地址比之前定义的局部变量地址小,说明栈是向上生长的

    7.将栈的大小设置为100字节,并定义一个200字节大小的数组(全局),打印出数组某些元素的地址(这边打印地址并不是为了看其地址,而是为了在程序里面有调用该数组,防止被编译器忽略),程序能够正常运行;

    8.栈大小不变,将数组大小设置为5,再定义一个200字节大小的数组(局部),打印出某些元素的地址(也是为了防止被编译器忽略),发现程序在执行到该局部数组所在的函数体后卡死了(之前的能够正常打印出来),原因:栈的地址超出了内存范围(0x20000000);

    9.其他不变,将全局数组大小设置为100,再编译运行程序,发现程序能够正常运行,原因:栈大小虽然比所需栈的大小小100,但是全局数组大小刚好为100,栈会占用全局变量的空间而不至于超出内存范围,这里也可以看出当栈溢出的时候程序不一定会死机,当内存访问越界的时候才必然会死机

    10.设置让编译器生成bin文件,然后编译,将CODE,RO-DATA,RW-DATA相加,发现其大小正好与bin文件的大小一模一样,一字节不差

    11.定义一个函数,函数里面的内容任意,但是程序里面并不调用该函数,编译发现CODE变大了,说明未使用的函数也是会占用flash空间的(注:并不是所有的都会)。

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值