STM32F1 MCU双向链表代码触发HardFault()栈溢出问题排查
STM32F1双向链表触发HardFault排查方案
核心定位方向
从固定循环次数触发异常、PC端运行正常的现象来看,栈溢出是高概率诱因,但也需排除链表操作的内存泄漏、野指针等问题。
1. 栈溢出的验证与修复
- 检查工程栈配置:在STM32F1启动文件(如
startup_stm32f10x_hd.s)中修改Stack_Size参数,默认值通常为0x400或0x800,可先调至0x1000测试。 - 验证栈溢出:在栈底放置魔术字(如
uint32_t stack_magic[4] = {0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF};),循环执行后检查魔术字是否被覆盖,确认栈是否越界。 - 优化局部变量:若
formArray()或confirmHandshake()中存在局部大数组,改为全局数组或动态分配(需在启动文件中调整Heap_Size开启堆功能)。
2. 链表操作的内存问题排查
PC端内存充足,不会暴露内存泄漏,MCU内存有限需重点检查:
- 节点分配/释放:若使用
malloc/free,需确保每次删除节点时正确调用free,避免内存泄漏导致后续分配失败触发HardFault。 - 双向链表指针逻辑:检查插入/删除节点时的指针指向,比如删除最早节点后,是否正确更新头/尾节点的
prev/next字段,防止野指针访问。 - 节点数据写入:轮询GPIO时写入链表节点的数据是否越界,避免覆盖节点的指针字段破坏链表结构。
3. 硬件相关潜在问题
- 中断栈冲突:若GPIO轮询过程中存在中断,中断栈与主栈共享,需确认中断是否占用过多主栈空间,可调整中断优先级或增大主栈。
- 稳定性排查:STM32F1若超频或供电不稳可能触发异常,但固定次数触发的概率极低,可暂不优先排查。
4. 代码关键检查点
针对你的业务逻辑,重点核对:
- 链表满插入逻辑:删除最早节点后,新节点的
prev是否关联到当前尾节点,next是否设为NULL,同时更新尾节点指针。 formArray()遍历:确认数组长度为16,遍历次数严格控制在16次,避免越界访问。confirmHandshake()校验:检查数组访问是否越界,是否存在对已删除链表节点的非法引用。
快速验证步骤
- 先调大启动文件的
Stack_Size,重新编译下载,观察是否仍触发HardFault。 - 若问题消失,说明是栈溢出,进一步定位占用栈空间较大的函数;若问题依旧,重点排查链表指针操作和内存释放逻辑。
内容的提问来源于stack exchange,提问作者2222
相关产品推荐
相关产品推荐

