【笔记8】嵌入式系统中的内存分段

        前几天参加了某外企二面,项目讲完没继续对着质询,上来就问了一道关于嵌入式系统堆栈段分配的问题。当时就已经知道这把又要塔西狼......所以今天赶紧查资料看网课,总算是把这块基础理论补齐了。

        在嵌入式系统中,内存管理和程序结构与Windows系统类似,但由于资源受限(如内存容量小、处理器性能低),需要更精细的优化。

        嵌入式系统的内存分段规则如下表所示:

           低地址Code Segment(代码段).text 程序代码
                |Const Segement (常量段),rodata 字面常量,字符串等
                |Global/Static Segement (全局/静态段)

声明未初始化的放 .bass

声明且初始化0放.bass

声明且初始化的放 .data

                |

Heap Segment(堆段)

向下增长

由编写代码的人分配内存释放(malloc&&free)
            高地址

Stack Segment(栈段)

变量先定义放高地址,bit先出现(高位)放高地址,向上增长

(小端序)

由编译器自动分配释放,存放局部变量、形参、返回值

 

1. 代码段

程序可执行代码存放的位置,详细包括

(1)编译后的机器指令

(2)字符串常量和define的常量

(3)程序正在执行的代码

物理位置:flash(闪存)中

2. 常量段

程序中RO(只读)数据存放的位置

(1)字符串、数字等常量存放在常量段

(2)const修饰的全局变量存放在常量段

(3)程序运行中此段的内容不可以被修改

物理位置:flash中,嵌入式系统中所有RO的数据都不会存放在SRAM中

3. 全局/静态段

.bass :

(1)未初始化的全局变量和未初始化的静态变量存放在.bss段。

(2)初始化为0的全局变量和初始化为0的静态变量存放在.bss段。

(3)bss段不占用exe空间,其内容由操作系统初始化。

  物理位置:SRAM(静态存储器)与计算机系统中的DRAM不同,SRAM不需要间断刷新电容来维持存储的内容。

.data:

  (1)  已初始化的全局/静态变量存放在.data段

(2)data段占用exe空间,内容由代码初始化生成

  物理位置: SRAM和flash

4. 堆段

此部分内存由开发者自由开辟,但是存在一个隐式指针不断地从低地址向高地址移动,所以Heap Segment的内存地址应该是从低到高增长的。此外,malloc自由开辟的内存使用完一定要用free去释放,否则会内存泄漏。

5. 栈段

什么时候会用到栈段?

(1)局部变量和const定义的局部变量

(2)入口参数和返回值(所以在一些算法题中,我们将返回数组视为不占内存

特点:

(1)由系统自动管理,无需手动开辟释放

(2)定义在栈段的变量,离开作用域后即被释放

(3)由高地址向低地址增长(这个好理解,微机原理里面遇到过很多类似),并且与数据结构中的栈结构进出规律相同,都是FIRST IN LAST OUT(FILO)

(4)使用起来速度快,但是没有自由度,最大空间较少

接下来分享一道例题:

//某函数内有
char szStr1[] = {'1', '0', '0', "\0', 'a', "\0', '0'};
char szStr2[6]= {'1', '0', '0', '0', '0', '0'};

//请问
strlen(szStr1)=???

sizeof(szStr1)=???

strlen(szStr2)=???

sizeof(szStr2)=???

第一问strlen遍历到\0停止,所以求出来长度是3

第二问Str1占了7Byte,所以答案是7

第三问......肯定有人会冲动的填6

这个题确实6,把博客里一大半知识点利用了。

我们重新从题干开始分析,首先这两行数组初始化是在某个函数中进行的,所以是局部变量。因此,接下来的分析应该全部围绕Stack Segment展开。

首先我们做了:

char szStr1[] = {'1', '0', '0', '\0', 'a', '\0', '0'};

所以,此行被执行后,栈段情况应该是;

                             1低地址
                             0 
                             0 
                             \0 
                             a 
                             \0 
                             0高地址

 

接着,我们压入:

char szStr2[6]= {'1', '0', '0', '0', '0', '0'};

这下子内存结构就变成了:

                          1             szStr2
                          0 

                          0

 
                          0 
                          0 
                          0 
                             1              szStr1
                             0 
                             0 
                             \0 
                             a 
                             \0 
                             0             高地址方向

这个时候我们对Str2做strlen,遍历指针到了szStr2表尾发现没有\0,它会继续向下遍历到szStr1里的\0前才停止。

所以得出来的字符串长度是9

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值