C语言-内存分布(STM32内存分析)

这篇具有很好参考价值的文章主要介绍了C语言-内存分布(STM32内存分析)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、内存组成

根据动静特性可以将内存分为动态区域静态区域代码段(Code)、只读数据段(RO data)、读写数据段(RW Data)、未初始化数据段(BSS)属于静态区域属于动态区域
C语言-内存分布(STM32内存分析),C/C++,c语言,stm32,java

二、静态区域

C语言-内存分布(STM32内存分析),C/C++,c语言,stm32,java

文本段 (Text / 只读区域 RO)

通常代码段和只读数据段合成为文本段(Text), 包含实际要执行的代码(机器指令)和 常量(常量区Ro data),例如字符串常量等。它通常是共享的,多个实例之间共享文本段。文本段是不可修改的。

已初始化读写数据段(RW data – Initialized Data Segment)

已初始化数据是在程序中声明,并且具有初值的变量,这些变量需要占用存储器的空间,在程序执行时它们需要位于可读写的内存区域内,并具有初值,以供程序运行时读写。

未初始化数据段(BSS – Block Started by Symbol)

未初始化的全局变量和静态变量,程序运行之前不需要占用存储器的空间,BSS段的变量只有名称和大小却没有值。
BSS段主要是为了节省可执行文件在磁盘上所占的空间,其仅仅记录变量所需的大小。储存未初始化的,或初始化为0的全局变量和静态变量。 BSS段属于静态内存分配,所以放在RAM里。
对未初始化的大型数组的节省效率比较明显。举例如下:

static int a[10000];  
int main()  
{  
}  

在上述程序中,若不存在 BSS 段,则可执行文件将开辟一个 10000 * sizeof(int) 大小的空间,并全部存储为0,int 为4字节的情况下,该变量将在磁盘上占用39KB的空间。但是此时若是存在BSS 段,则在可执行文件中,将只是记录现在的BSS段总大小为40000即可,而无需真正的占据39KB的空间.

代码优化对BSS段的影响:全局变量与静态变量没有初始化或初始化值为0时,都会放在.bss段。初始化为非0值,则放在.data段。考虑以下两个静态变量分别存储在哪个段中:

static int x1 = 1;  
static int x2 = 0;  

很明显可以看出,X1将被发在.data段中。令人意外的是 X2 将被放置在 .bss 段中,因为 x2 的值为0,被认为是未初始化的,因此将会被放在 .bss 段中以节省磁盘空间。

三、动态区域

对于程序运行过程中的内存使用,堆和栈一般是相向扩展的。堆的分配由程序来分配,但是栈是由编译器管理的。
C语言-内存分布(STM32内存分析),C/C++,c语言,stm32,java

堆(heap)

  • 堆内存只在程序运行时出现,一般由程序员分配和释放。在具有操作系统的情况下,如果程序没有释放,操作系统可能在程序(例如一个进程)结束后回收内存。注意它与数据结构中的堆是两回事,其操作方式类似于数据结构中的链表

  • 当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);

  • 当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

FreeRTOS的内存分配有五个方案: 如果申请的内存空间都在一个连续的空间内heap_4就够用了,但如果存在部分空间申请在内部RAM、部分在外部RAM,这时候就需要使用heap_5方案了,heap_5是在heap_4基础上实现的。

特点 缺点
heap_1 简单、不支持内存释放 需要管理内存空间
heap_2 支持内存释放,不支持碎片管理 需要管理内存空间、碎片问题
heap_3 malloc-free操作简单 碎片问题
heap_4 支持碎片管理 需要管理内存空间
heap_5 支持多个不连续内存空间,碎片管理 需要管理内存空间

栈(stack)

栈内存只在程序运行时出现,在函数内部使用的局部变量函数的参数以及返回值将使用栈空间,栈空间由编译器自动分配和释放。其操作方式类似于数据结构中的栈

例一:静态存储区、栈区、堆区

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
	char *a = "hello 1";	//静态存储区
	char b[] = "hello 2";	//栈区
	char *c = (char *)malloc(sizeof(b));	//堆区
	memcpy(c, "hello 3", sizeof(b));

	//a[2] = 'C';	//操作静态区会报错,只读不可修改
	b[2] = 'C';		//操作栈-修改成功
	c[2] = 'C';		//操作堆-修改成功
	printf(" a:%p %s\n b:%p %s\n c:%p %s\n",a,a,b,b,c,c);
    return 0;
}

程序运行结果如下

 a:0000000000404000 hello 1
 b:000000000061FE08 heClo 2
 c:00000000007F1400 heClo 3

四、STM32 内存分析

在对于RAM紧缺的嵌入式系统中,是缺少MMU内存管理单元的。因此在一些嵌入式系统中,比如常用的STM32来讲,内存映射被划分为闪存段(也被称为Flash,用于存储代码和只读数据)和 RAM段,用于存储读写数据。

在《ARM Cotrex-M3权威指南》中有关 M3的存储器映射表:
C语言-内存分布(STM32内存分析),C/C++,c语言,stm32,java

STM32的Flash和RAM地址范围,从图中我们可以看出,RAM地址是从0x2000 0000开始的,Flash地址是从0x8000 0000开始的。

Flash区域

C语言-内存分布(STM32内存分析),C/C++,c语言,stm32,java
如上图所示,Flash又可以分为这么几个部分。

  • 分别是文本段(Text) ,其中文本段中又包含可执行代码(Executable Code)和常量(Literal Value),在文本段之后就是只读
  • 数据区域(Read Only Data),当然并不是所有架构的单片机都满足这样一个排布规律,这里只针对于ARM Cortex M3系列的
  • 只读数据段后面接着的就是数据复制段(Copy of Data Section),第一次遇见这个概念的朋友看到数据复制可能会有疑惑,其实这个段充当的作用是存放程序中初始化为非0值得全局变量的初始值之所以要将初始值存放到这里 是因为全局变量是存放在RAM上的,RAM上的值掉电便丢失,每次上电之后这些变量是要重新赋值的,而重新赋值的值就存放在这里 那为什么不存放初始化为0的全局变量的初始值呢,原因也很简单,既然是初始化为0,那么在上电之后统一对存放初始化为0的全局变量的那块区域清0就好。

RAM区域

C语言-内存分布(STM32内存分析),C/C++,c语言,stm32,java
如上图所示,RAM中包含了如下几个部分,

  • 栈(Stack):存放局部变量和函数调用时返回的地址
  • 堆(heap):由malloc申请,free释放
  • bss:存放未初始化或者是初始化为0的全局变量
  • data:存放初始化为非0的全局变量

map文件分析

Code RO Data RW Data ZI Data
Executable Code Read Only Data data
  • 程序占用 Flash = Code + RO data + RW data

  • 程序运行时候占用 RAM = RW data + ZI data

  • Code + RO data + RW data 的大小也是生成的 bin 文件的大小文章来源地址https://www.toymoban.com/news/detail-675856.html

到了这里,关于C语言-内存分布(STM32内存分析)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32-程序占用内存大小计算

    STM32中程序占用内存容量 Keil MDK下Code, RO-data,RW-data,ZI-data这几个段: Code存储程序代码。 RO-data存储const常量和指令。 RW-data存储初始化值不为0的全局变量。 ZI-data存储未初始化的全局变量或初始化值为0的全局变量。 占用的Flash=Code + RO Data + RW Data; 运行消耗的最大RAM= RW-data+ZI-dat

    2024年02月04日
    浏览(47)
  • FreeRTOS内存管理 基于STM32

    目录 一、内存管理的基本概念 二、内存管理的应用场景 三、heap_4.c 1.内存申请函数 pvPortMalloc() 2.内存释放函数 vPortFree()  四、内存管理的实验 五、内存管理的实验现象       在计算系统中,变量、中间数据一般存放在系统存储空间中,只有在实际使用时才将 它们从存储空

    2024年02月14日
    浏览(57)
  • STM32定义变量到指定内存位置

    rt thread , 怎么定义变量到指定内存位置? OpenCat是由未来可编程机器人宠物制造商Petoi开发的基于Arduino和Raspberry Pi的开源四足机器人宠物框架。 定义一个宏 使用 修改链接文件 定义一个宏 使用

    2024年02月12日
    浏览(61)
  • STM32 hal库使用笔记(四)DMA—内存到内存/内存到外设

    目录 一、简介 1.DMA简介 2.一些概念 3.工作原理 二、HAL库的配置 1.时钟树的设置 2.DMA配置 2.1 内存到内存(代码对应3.1) 2.2 内存到外设(代码对应3.2) 三、代码编写 一、简介 1.DMA简介     DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设和存储器或者存储器和存储器之

    2024年02月04日
    浏览(37)
  • STM32查看内存占用的map文件解析

    双击工程名尽可打开xxx.map文件,里面主要显示了文件及函数使用内存的大小 堆:是用户调用malloc()时申请的内存; 栈:是提供给局部变量使用的,即由c语言机制自动申请和释放; 1.2 flash、ROM、RAM的区别 在stm32中flash就是ROM,掉电数据不会丢失;(通常保存着text段、Code、R

    2024年02月11日
    浏览(41)
  • STM32CubeMX教程12 DMA 直接内存读取

    开发板(正点原子stm32f407探索者开发板V2.4) STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX软件配置STM32F407开发板上 串口USART1以DMA方式传输数据 ,然后实现与实验“STM32CubeMX教程9 USART/UART 异步通信”相同的目标

    2024年02月03日
    浏览(83)
  • STM32微机系统框架、内存、存储器、寄存器

    大家好,我是 杰哥嵌入式开发 最近在出定时器系列, 但是线下班有一些学生在学习完C语言之后, 在51接触各种寄存器和对软件代码各种操作是如何在单片机系统中起到作用的感到非常的不解, 经过我的初步分析,是对嵌入式微机系统的大概雏形系统框架不熟悉导致。 所以

    2024年02月06日
    浏览(59)
  • STM32深入系列01——内存简述(Flash和SRAM)

    ==== 文章汇总(有代码汇总) ==== 最近学到了 内存池、IAP 相关的知识,虽然明白大致的过程,但是对于具体的很多数字还是有些似懂非懂,因此又回来稍微细致的总结一下,方便理解。 STM32是一个 32位 的单片机,因此,它有 32根地址线 ,每个地址线有两种状态:导通 或 不

    2024年02月09日
    浏览(39)
  • stm32 freeRTOS lwip TCP快速发送,内存泄露问题

    现象1: 发送缓慢,tcp_write之后要等200多ms才能过发送出去,而且粘包严重。 解决办法 tcp_write之后,立马调用tcp_output ,tcp就会立马发送。 现象2: 持续快速发送和接受TCP数据出现断言 而且出现TCP断连,死机情况。 其实就是一句话 主程序和以太网中断程序中对PCB-unsent 之类的

    2024年02月08日
    浏览(37)
  • STM32 | STM32时钟分析、GPIO分析、寄存器地址查找、LED灯开发(第二天)

    寄存器 :寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成 在计算机领域,寄存器是CPU内部的元件,包括通用寄存器、专用寄存器和 控制寄存器 。寄存

    2024年03月08日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包