一次栈溢出导致 Modbus 寄存器被篡改的排查实录
一、问题现象
某日测试发现,在执行操作A之后通过modbus poll查看操作A次数,本来是每次+1的,但是操作A执行后,modbus_data_calib.dark_calib 计数不再正常 +1,而是变为异常大的数值;同时该结构体其他成员也被篡改,初步判定为踩内存。 (modbus_data_calib地址0x20058C9A,全局结构体)


二、定位过程
1.对全局结构体 modbus_data_calib 设置写访问断点,监控其内存被修改的行为
按下ctrl+B,对该变量添加
2.复现问题,发现断点停在xMBPortSerialGetByte(&ucByte)这个函数中,发现写入地址 0x20058CA0 恰好落在全局变量 modbus_data_calib 区域内。
这说明:栈溢出后,栈指针越界,直接踩穿到了 .bss 段全局变量。
3.查看工程map文件,看内存分布情况,从 MAP 文件可见:
全局变量 .bss 结束于 0x20058FFF
栈(STACK)起始于 0x20059200,大小仅 1024 字节(1KB)
栈向下生长,溢出后会直接覆盖下方 .bss 全局变量
栈从高地址向低地址生长,而.bss段在低地址,栈溢出时会直接踩到相邻的全局变量区

4.现在基本确定是栈溢出了,下面开始排查什么地方导致的栈溢出。该问题属于高概率问题,可以通过断点逐步调试,定位到具体哪个函数。在执行操作A后,在操作A函数开头打上断点,随后逐步调试,最后将函数锁定在WriteDark 函数中,函数内定义了局部数组 u16 temp_buf[1024],大小为 2KB,但系统栈仅 1KB,函数调用时栈瞬间溢出,覆盖相邻的 .bss 全局变量区。
三、问题解决
- 局部大数组改为 static 或全局变量(放入 .bss,不占栈)
- 适当增大栈空间(如从 1K → 2K/4K)
- 禁止在函数内定义 >512 字节的局部数组
四、思考
如何在前期预防住栈溢出的风险?欢迎大家留言。
我是王工,关注我,不定期分享嵌入式相关经验







浙公网安备 33010602011771号