写STM32程序时,总绕不开“堆”和“栈”这两个词。它们像内存里的“临时工”和“动态侠”,一个管自动分配,一个管手动申请,用好了程序稳如老狗,用错了直接“卡死”。今天用最直白的话,拆解这两个关键概念。

1、栈(Stack)
作用:存函数局部变量、参数、返回地址,以及中断时的寄存器状态(保护现场)。
特点:
自动管理:编译器自动分配/释放,函数调用时压栈,返回时弹栈。
后进先出(LIFO):像叠盘子,最后放的先拿走。
固定方向:从高地址向低地址增长(栈顶指针向下移动)。
风险:
栈溢出:局部变量太大或递归太深,会覆盖其他内存,导致程序崩溃。
生命周期短:函数返回后,栈里的数据自动消失,不能返回栈变量的地址。
2、堆(Heap)
作用:动态分配内存(如用malloc申请数组、结构体),适合运行时大小不确定的数据。
特点:
手动管理:程序员用malloc申请,用free释放,忘记释放会内存泄漏。
自由度高:可以随时申请/释放,但需自己控制大小和碎片。
固定方向:从低地址向高地址增长(堆指针向上移动)。
风险:
内存泄漏:申请后不释放,堆空间被占满,程序卡死。
碎片化:频繁申请/释放会导致堆里出现不连续的小空闲块,无法分配大内存。
3、避坑指南
栈溢出:
减少函数内大数组(如int buf[1024]),改用全局变量或动态分配。
避免深递归,用循环替代。
堆泄漏:
申请后必须释放,配对使用malloc/free。
避免频繁申请小内存,尽量一次性分配足够空间。
调试技巧:
用MDK的Map文件查看堆栈大小配置。
开启编译器的栈溢出检测(如--stack_usage)。
本文凡亿教育原创文章,转载请注明来源!

扫码关注





































