C语言-内存分布(STM32内存分析)
C/C++内存分布
- 一、内存组成
- 二、静态区域
- 文本段 (Text / 只读区域 RO)
- 已初始化读写数据段(RW data -- Initialized Data Segment)
- 未初始化数据段(BSS -- Block Started by Symbol)
- 三、动态区域
- 堆(heap)
- 栈(stack)
- 四、STM32 内存分析
- Flash区域
- RAM区域
- map文件分析
一、内存组成
根据动静特性可以将内存分为动态区域和静态区域,代码段(Code)、只读数据段(RO data)、读写数据段(RW Data)、未初始化数据段(BSS)属于静态区域。堆和栈属于动态区域。

二、静态区域

文本段 (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 段中以节省磁盘空间。
三、动态区域
对于程序运行过程中的内存使用,堆和栈一般是相向扩展的。堆的分配由程序来分配,但是栈是由编译器管理的。

堆(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 1b:000000000061FE08 heClo 2c:00000000007F1400 heClo 3
四、STM32 内存分析
在对于RAM紧缺的嵌入式系统中,是缺少MMU内存管理单元的。因此在一些嵌入式系统中,比如常用的STM32来讲,内存映射被划分为闪存段(也被称为Flash,用于存储代码和只读数据)和 RAM段,用于存储读写数据。
在《ARM Cotrex-M3权威指南》中有关 M3的存储器映射表:

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

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

如上图所示,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 文件的大小
相关文章:
C语言-内存分布(STM32内存分析)
C/C内存分布 一、内存组成二、静态区域文本段 (Text / 只读区域 RO)已初始化读写数据段(RW data -- Initialized Data Segment)未初始化数据段(BSS -- Block Started by Symbol) 三、动态区域堆(…...
Linux上配置NAT
Linux系统上实现NAT上网是一个挑战性的任务,需要对操作系统进行合理的配置。本文将概述在Linux上实现NAT上网,并给出相应的工作步骤。 NAT,即Network Address Translation,是一种网络部署技术,可以在peivate network&…...
springboot实现简单的消息对话
目录 一、前言 二、实战步骤 步骤 1: 步骤 2: 步骤 3: 步骤 4: 一、前言 要在Spring Boot项目中实现消息对话,你可以使用WebSocket技术。WebSocket是一种在客户端和服务器之间提供实时双向通信的协议。 二、实…...
「Tech初见」Linux驱动之blkdev
目录 一、Motivation二、SolutionS1 - 块设备驱动框架(1)注册块设备(2)注销块设备(3)申请 gendisk(4)删除 gendisk(5)将 gendisk 加入 kernel(6&a…...
ssh配置(二、登录服务器)
一. 登录 linux 服务器的两种方式 使用 ssh用户名密码 的方式登录,但这种方式不安全,密码太简单容易被暴力破解,密码太复杂又不容易记。使用 ssh公私钥 的方式登录。 以上两种方式都可以在图形化软件工具中配置,例如 finalshell…...
pytorch异常——RuntimeError:Given groups=1, weight of size..., expected of...
文章目录 省流异常报错异常截图异常代码原因解释修正代码执行结果 省流 nn.Conv2d 需要的输入张量格式为 (batch_size, channels, height, width),但您的示例输入张量 x 是 (batch_size, height, width, channels)。因此,需要对输入张量进行转置。 注意…...
【FPGA项目】沙盘演练——基础版报文收发
第1个虚拟项目 前言 点灯开启了我们的FPGA之路,那么我们来继续沙盘演练。 用一个虚拟项目,来入门练习,以此步入数字逻辑的…...
【C++技能树】继承概念与解析
Halo,这里是Ppeua。平时主要更新C,数据结构算法,Linux与ROS…感兴趣就关注我bua! 继承 0. 继承概念0.1 继承访问限定符 1. 基类和派生类对象赋值兼容转换2. 继承中的作用域3. 派生类中的默认成员函数4.友元5.继承中的静态成员6.菱…...
计算机网络 第二节
目录 一,计算机网络的分类 1.按照覆盖范围分 2.按照所属用途分 二,计算机网络逻辑组成部分 1.核心部分 (通信子网) 1.1电路交换 1.2 分组交换 两种方式的特点 重点 2.边缘部分 (资源子网) 进程通信的方…...
无涯教程-机器学习 - 矩阵图函数
相关性是有关两个变量之间变化的指示,在前面的章节中,无涯教程讨论了Pearson的相关系数以及相关的重要性,可以绘制相关矩阵以显示哪个变量相对于另一个变量具有较高或较低的相关性。 在以下示例中,Python脚本将为Pima印度糖尿病数…...
Redis 高可用与集群
Redis 高可用与集群 虽然 Redis 可以实现单机的数据持久化,但无论是 RDB 也好或者 AOF 也好,都解决 不了单点宕机问题,即一旦单台 redis 服务器本身出现系统故障、硬件故障等问题后, 就会直接造成数据的丢失,因此需要…...
修改文件名后Git仓上面并没有修改
场景: 我在本地将文件夹名称由Group → group ,执行git push 后,远程分支上的文件名称并没有修改。 原因: 是我绕过了git 直接使用了系统的重命名操作。 在 Git 中,对于已经存在的文件或文件夹进行大小写重命名是一个敏感的操作…...
Linux 信号
目录 基本概念信号的分类可靠信号与不可靠信号实时信号与非实时信号 常见信号与默认行为进程对信号的处理signal()函数sigaction()函数 向进程发送信号kill()函数raise() alarm()和pause()函数alarm()函数pause()函数 信号集初始化信号集测试信号是否在信号集中 获取信号的描述…...
深入探讨梯度下降:优化机器学习的关键步骤(二)
文章目录 🍀引言🍀eta参数的调节🍀sklearn中的梯度下降 🍀引言 承接上篇,这篇主要有两个重点,一个是eta参数的调解;一个是在sklearn中实现梯度下降 在梯度下降算法中,学习率…...
高频算法面试题
合并两个有序数组 const merge (nums1, nums2) > {let p1 0;let p2 0;const result [];let cur;while (p1 < nums1.length || p2 < nums2.length) {if (p1 nums1.length) {cur nums2[p2];} else if (p2 nums2.length) {cur nums1[p1];} else if (nums1[p1] &…...
Hive-启动与操作(2)
🥇🥇【大数据学习记录篇】-持续更新中~🥇🥇 个人主页:beixi 本文章收录于专栏(点击传送):【大数据学习】 💓💓持续更新中,感谢各位前辈朋友们支持…...
css transition 指南
css transition 指南 在本文中,我们将深入了解 CSS transition,以及如何使用它们来创建丰富、精美的动画。 基本原理 我们创建动画时通常需要一些动画相关的 CSS。 下面是一个按钮在悬停时移动但没有动画的示例: <button class"…...
LeetCode 面试题 02.05. 链表求和
文章目录 一、题目二、C# 题解 一、题目 给定两个用链表表示的整数,每个节点包含一个数位。 这些数位是反向存放的,也就是个位排在链表首部。 编写函数对这两个整数求和,并用链表形式返回结果。 点击此处跳转题目。 示例: 输入&a…...
一米脸书营销软件
功能优势 JOIN ADVANTAGE HOME PAGE MARKETING 公共主页营销 可同时对多个账户公共主页评论,点赞等 可批量邀请多个好友对Facebook公共主页进行评论点赞等,也可批量登录小号对自己公共主页进行点赞。 GROUP MARKETING 小组营销 可批量针对不同账户进行…...
vue 根据数值判断颜色
1.首先style样式给两种颜色 用:class 三元运算符判断出一种颜色 第一步:在style里边设置两种颜色 .green{color: green; } .orange{color: orangered; }在取数据的标签 里边 判断一种颜色 :class"item.quote.current >0 ?orange: green"<van-gri…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
规则与人性的天平——由高考迟到事件引发的思考
当那位身着校服的考生在考场关闭1分钟后狂奔而至,他涨红的脸上写满绝望。铁门内秒针划过的弧度,成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定",构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...
TJCTF 2025
还以为是天津的。这个比较容易,虽然绕了点弯,可还是把CP AK了,不过我会的别人也会,还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...
大数据驱动企业决策智能化的路径与实践
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:数据驱动的企业竞争力重构 在这个瞬息万变的商业时代,“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...
