027、短帧高频发送下的缓冲区溢出
那个凌晨三点的日志
现场设备每隔几分钟就重启一次,看门狗日志里全是复位记录。用户投诉到老板那里,老板凌晨两点把我从被窝里拽起来。我连上调试口,盯着串口输出看了半小时,发现一个诡异的现象:系统正常运行,偶尔打印几行状态信息,然后突然停止打印,再过几秒就重启了。
没有崩溃栈,没有断言失败,没有内存越界报警。就像一个人走着走着突然倒地,尸检报告写着"心脏骤停",但你知道他心脏本来没问题。
后来花了整整两天,才定位到罪魁祸首:一条短帧发送路径。数据长度只有十几个字节,发送频率极高,每秒几百次。出问题的不是发送本身,而是发送完成后的回调处理里,往一个固定大小的环形缓冲区写数据时,没有正确处理"剩余空间不足"的情况。
这个坑,公开资料里几乎没人讲过。因为大多数教程教你的是"环形缓冲区怎么实现",而不是"高频写入时环形缓冲区怎么背叛你"。
环形缓冲区的隐形陷阱
先明确一个前提:这里说的缓冲区溢出,不是经典的安全漏洞意义上的栈溢出,而是逻辑层面的"写指针越界"或"数据覆盖"。在嵌入式通信场景里,这种溢出往往不触发硬件异常,因为写操作落在合法的内存地址范围内,只是覆盖了不该覆盖的数据。
环形缓冲区有一个极其容易被忽略的特性:当写指针追上读指针时,你面临两个选择——覆盖旧数据,还是丢弃新数据。很多实现选择了"覆盖旧数据",因为这样写操作永远不会失败。但在短帧高频发送场景下,这个选择会变成一个定时炸弹。
为什么?因为高频发送意味着生产者的速度远大于消费者。你每秒往缓冲区里塞几百条短帧,而消费者可能因为调度