当前位置: 首页 > news >正文

嵌入式系统C语言资源分类与内存分布分析

1.C语言存储分类总览

在C语言/嵌入式程序运行中,内存通常被划分为以下几个主要区域:

  • 代码段(Code Segment / .text):用于存放程序的机器指令(即编译后的代码)。这部分通常是只读的,以防止程序在运行时意外修改指令。
  • 数据段(Data Segment / .data):存放程序中已初始化的全局变量和静态变量。
  • BSS段(.bss):存放程序中未初始化的或初始化为0的全局变量和静态变量。BSS不占用可执行文件的实体存储空间,只记录所需空间大小。
  • 堆(Heap):用于程序运行时的动态内存分配(如C语言中的malloc/free)。这部分内存由程序员手动申请和释放,若不释放容易造成内存泄漏。其生长方向通常是向高地址生长的。
  • 栈(Stack):用于存放局部变量、函数参数、返回地址、中断现场保护数据等。由编译器/CPU自动分配和释放。其生长方向通常是向低地址生长的。

2.C变量到底住哪里

3. 常见误区

  • const 全局:住.rodata(只读)
  • const 局部:绝大多数还是栈,只有编译器优化后可能放到 .rodata
  • 函数内static:不占栈,编译期就分好 RAM位置(.data 或 .bss),只是作用域限制在函数内

4. .data vs .bss关键差异

5. 堆 vs 栈

6. 每个线程的栈从哪来

关键:每个RTOS线程有独立的栈。栈本身住在哪里,看创建方式

rt_thread_t t = rt_thread_create("foo", foo_entry, NULL, 8 * 1024, // ← 栈大小 8 KB 15, 10);

rt_thread_create内部调用rt_malloc(stack_size)从堆里分配栈!所以

  • 主线程 / 内核线程等在启动时静态分配,不吃heap
  • 线程越多,heap越吃紧

7.内存(RAM)、堆、栈、Flash 之间的关系

在嵌入式硬件语境下,Flash通常等同于只读存储器(ROM),断电不丢失数据;而内存(Memory)通常指静态或动态随机存储器(SRAM/SDRAM/RAM),断电会丢失数据。

在大多数嵌入式系统(如基于ARM Cortex-M的单片机)中,RAM的物理地址是从低到高排列的。软件层面将这块物理空间划分成了如下结构:

它们的关系可以从物理存储程序运行两个维度来理解:

1. 物理层面的包含关系

  • 内存(RAM)包含了堆和栈。堆和栈只是RAM在软件层面上划分出来的两块不同用途的工作区域。
  • 内存(RAM)还包含了数据段和BSS段(的运行时状态)。

2. 程序断电与通电(启动)时的Flash与RAM的关系

烧录/断电状态下(仅Flash):
Flash中不仅存储了代码段(程序指令)和常量区(如const修饰的全局变量、字符串常量),还存储了数据段(Data)的初始值。因为RAM断电会丢失数据,全局/静态变量的初始值必须保存在Flash中。

嵌入式系统上电复位时,会执行一段启动代码(Startup Code),它会做两件关键的事情:

  1. 将Flash中存储的数据段初始值拷贝到RAM的数据段中。
  2. 在RAM中划分出一块区域作为BSS段,并将其全部清零。
  3. 初始化栈指针(SP),将RAM剩下的空间按需划分为堆(Heap)栈(Stack)供程序运行使用。

3. 堆(Heap)与 栈(Stack)在内存中的博弈

在有限的嵌入式RAM中,堆和栈通常位于未使用RAM区域的两端:

  • 栈(Stack)通常位于较高地址,向下(低地址)生长。
  • 堆(Heap)通常位于较低地址,向上(高地址)生长。
  • 关系与风险:两者共享剩余的RAM空间。如果局部变量开辟过大(如深层递归、巨大的局部数组),或者动态分配内存过多,导致堆和栈的边界相撞,就会发生栈溢出(Stack Overflow),这是嵌入式系统程序崩溃的常见原因。

总结:
Flash是代码和初始数据的“永久仓库”;内存(RAM)是程序运行的“临时工作台”。在RAM这个工作台上,数据段和BSS段放的是长期的“公共工具”(全局/静态变量),放的是随用随扔的“临时草稿”(局部变量),而则是根据需要随时划出来的“自由拼装区”(动态内存)

http://www.cnnetsun.cn/news/4057268.html

相关文章:

  • 第33篇 STL之stack与queue:BFS/DFS的标配数据结构,面试手写不过分吧
  • FastApi进阶
  • 一文速通GPU版FFmpeg视频转码的安装使用
  • 传统BIOS引导黑苹果实战:老硬件安装macOS Monterey完整指南
  • 基于大模型的PLC编程自动化:从自然语言到工业控制代码的智能生成
  • 无线传输模块概述
  • Python 快速上手(Java 开发者版)
  • 碰到文档色差别发愁,AI 导出鸭帮你搞定 DeepSeek 导出 pdf 颜色不一样怎么办的实操解决技巧
  • Gitee实战指南:从Git基础到团队协作的完整工作流
  • 微信聊天记录导出工具WeChatMsg:免费开源,永久保存你的每一句对话
  • AI如何重塑经济模式:从传统支柱解构到新价值创造
  • Unity-2D-Destruction 完全指南:免费开源 2D 精灵破碎工具,5 分钟实现爆炸破坏效果
  • 2024黑苹果安装指南:从硬件选型到OpenCore配置实战
  • Linux文件IO编程指南:系统IO与标准IO的核心区别与实战应用
  • 海纳斯新机开荒指南:系统设置调优、应用安装与卸载全攻略
  • 腾讯云部署OpenClaw对接钉钉机器人:AI智能体自动化办公实战
  • Linux内存优化实战:从free命令解读到性能调优全解析
  • TG地理围栏实战:构建毫秒级响应的实时位置监控系统
  • OpenClaw智能体框架实战:从零搭建AI自动化工作流
  • fflip 升级迁移指南:特性开关从 v2 到 v4 平滑升级避坑全攻略
  • 项目沟通管理:从理论到实践,打造高效团队协作的通信协议
  • git-sync 系统服务配置:使用 systemd 实现无人值守的定时备份
  • AudioBand常见问题排查清单:10个高频错误与解决方案
  • 打造类似Apple Music的动画效果:kavsoft-swiftui-animations中的音乐应用案例
  • 覆盖12+编程语言:palenight.vim 多语言语法高亮适配详解
  • PyQt-Frameless-Window 常见问题排查清单:从 DLL 加载失败到毛玻璃卡顿
  • MXFP8量化原理揭秘:NVIDIA-Nemotron-3.5-Lightning-30B-A3B-mxfp8如何把31B模型压缩到30GB
  • 深度解析North-Micro-Vision-Instruct-mxfp8架构:Cohere Compass的混合注意力与DeepStack视觉编码器
  • dsh-web-ui 安全使用指南:配对门、隧道与 SSH 的 6 条安全建议
  • ClimaX Docker部署实战:一条命令启动完整气象模型环境