这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 堆heap在STM32中的作用与使用

共16条 1/2 1 2 跳转至

堆heap在STM32中的作用与使用

院士
2026-07-27 15:41:41   被打赏 25 分(兑奖)     打赏
堆heap在STM32中的作用与使用

在STM32嵌入式开发中,‌堆(Heap)‌的主要作用是提供‌动态内存分配‌的能力。与栈(Stack)由编译器自动管理不同,堆内存由程序员在程序运行时手动申请和释放。

核心作用:动态内存管理

堆主要用于存储那些需要在‌运行时动态创建和销毁的数据‌,有别于在函数内部声明的临时使用的数组,缓冲空间等。

  • 动态数组/缓冲区‌:当涉及到不定长度的数据包接收时、网络通信中的数据包缓冲、音频/图像处理的临时缓冲区等,需要共享使用一整片RAM的时候。

  • 动态数据结构‌:如链表、树、队列等需要频繁插入和删除节点的结构。

  • 对象生命周期管理‌:在C++开发中,使用 new 创建的对象通常存储在堆上,直到使用 delete 释放。

实现方法

  • ‌程序员主动操作分配与释放‌:

    • 使用标准C库函数 malloc(), calloc(), realloc() 后,程序将从堆中申请内存。

    • 使用 free() 释放不再使用的内存。

    • 如果忘记释放,会导致‌内存泄漏‌,最终耗尽RAM导致系统崩溃。

  • ‌内存布局‌:

    • 在STM32的RAM分布中,堆通常位于静态数据区(.data/.bss)之后,栈之前(或相邻,取决于链接脚本设置)。

    • 堆是从低地址向高地址增长的(与栈的高到低增长相反)。

STM32堆与PC端区别

在PC机上,堆空间通常很大且由操作系统管理;而在STM32等裸机或RTOS环境中,堆有以下显著特点:

特性通用操作系统STM32 (裸机/嵌入式)
空间大小极大 (GB级别)极小‌ (STM32F103有20KB,STM32F407有192KB)
配置方式操作系统自动管理需在启动文件(.s)或链接脚本(.ld)中手动指定 Heap_Size
默认大小动态扩展默认通常很小 (如 Keil MDK 默认为 0x200 即 512字节)
碎片问题有成熟算法处理极易产生内存碎片‌,频繁 malloc/free 可能导致虽有空闲但无法分配连续大块内存
效率较高相对较低,malloc 执行时间不确定,不适合硬实时要求极高的场景

STM32中堆设置

在STM32工程中,堆的大小是在启动文件(如 startup_stm32f407xx.s)中定义的。

; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size      EQU     0x200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

如果使用STM32CubeMX配置的话,在Project Manager选项页里面配置

堆设置01.jpg

使用建议与最佳实践

  • 不使用malloc()函数:由于嵌入式系统RAM有限且无虚拟内存保护,频繁的动态分配容易导致内存碎片和泄漏。

  • 优先使用静态分配‌:对于大小已知或可预估的缓冲区,优先使用‌全局数组‌、‌静态局部变量 (static)‌ 或‌栈上数组‌(注意栈溢出风险)

  • 大数组放全局/静态区‌:如果数组较大(如超过1KB),建议定义为全局变量或 static 变量,存放在 .bss 或 .data 段,而不是放在堆或栈上,这样更稳定且易于管理。

对于RTOS来说(如FreeRTOS),RTOS 通常有自己的内存管理堆(configTOTAL_HEAP_SIZE ),这与C标准库的堆是两回事。在FreeRTOS中调试的malloc()函数是重映射移植之后的,其实际是对声明的全局数组的数据再分配。

  • 如果不使用 malloc:可以将 Heap_Size 设为 0,以节省RAM空间给栈或全局变量。

总结

STM32中的堆是一个‌有限的、手动管理的动态内存池‌。它的主要价值在于提供灵活性,允许程序在运行时根据需要分配内存。但由于其资源受限和潜在风险(碎片、泄漏),在嵌入式开发中应‌节制使用‌,优先考虑静态内存分配方案。一句话,不使用malloc!




关键词: heap         

助工
2026-07-28 23:17:12   被打赏 10 分(兑奖)     打赏
2楼

MCU的开发还是少使用malloc()函数吧


工程师
2026-07-29 14:09:27   被打赏 10 分(兑奖)     打赏
3楼

可以把heap设置为0呀!

看样子又可以节省512B的 RAM空间。


工程师
2026-07-31 10:34:38   被打赏 20 分(兑奖)     打赏
4楼

malloc()一定要及时的释放。动态内存申请,一旦出问题,会引起一些莫名其妙的问题,好难排查的。


菜鸟
2026-07-31 10:36:13   被打赏 20 分(兑奖)     打赏
5楼
完全认同,MCU 项目能不用 malloc 就不用,堆直接置 0 还能省内存,量产长期运行再也不怕莫名死机、HardFault。



高工
2026-07-31 10:38:14   被打赏 30 分(兑奖)     打赏
6楼

看怎么用咯,我就很喜欢用,一般是统一申请统一释放,不存在什么申请释放不成对的情况(算法动态开关,所需要的内存就动态申请释放)。相比较于malloc和free,我倒是觉得内存越界才是更难处理和排查的问题。


专家
2026-07-31 10:45:57   被打赏 20 分(兑奖)     打赏
7楼

感谢分享!想补充问一下,如果用 Keil 的话,除了看 Map 文件,还有没有更直观的方法实时监控堆的剩余量?避免跑飞了才查 HardFault。


助工
2026-07-31 11:00:45   被打赏 30 分(兑奖)     打赏
8楼

嵌入式heap如果管理不好,1很容易造成内存泄露(申请没有释放),长时间会申请不到内存。解决这个问题必须严格mallo和free对齐  2。因为小内存使用多,多次使用,内存碎片(内存空洞)就会占据很多,导致系统申请不到大内存。  解决这个问题基本是会设置几个固定大小内存池,小空间在这些内存池申请。大空间在heap申请。


院士
2026-07-31 10:59:12   被打赏 10 分(兑奖)     打赏
9楼

在 startup_stm32f4xx.s 中找到 Heap_Size EQU 0x00000400,将其改为 0x00000000。


助工
2026-07-31 11:01:33   被打赏 10 分(兑奖)     打赏
10楼

可以在VSCode中,用Map View Embedded插件,可视化查看分配情况吧?


共16条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]