[经验分享] 单片机程序中隐藏的数据溢出陷阱

[复制链接]
71|27
Zhiniaocun 发表于 2026-3-12 18:46 | 显示全部楼层 |阅读模式
单片机程序中隐藏的数据溢出陷阱
通常的规则: 当代码中对char、short等更短的类型进行算术运算时,编译器会自动将它们提升为int再进行计算。

假设16位、32位无符号数类 型,分别定义为UINT16、UNIT32


一.计算过程溢出

    对16bit单片机,如以下程序
    UINT16 a, b, c;
    c = (a * b)/10;
    故障描述:当a=6554,b = 10,但c出错,(6554*10)/10 != 6554;
    原因分析:a * b = 65540,按unsigned int为16bit计算已溢出;
    解决方案:c = ((UNIT32)a * b)/10; //手动提升a到32bit


二.移植后溢出

1. 16位单片机,正常运行


    设计如下程序, 在主循环中运行10次,处理某件事1次
    UINT16 a=0, a0=0;

    a++;//记录运行次数,a达到0xffff后+1溢出为0
    if((a-a0) >= 10)
    {
        a0 = a;//记录当前时刻
        //处理其它逻辑
    }   

    当a0=65530,a=4(a当前65530,经过10次运行,变成4,)时处理事情
    在程序中,UINT16就是本机字长,直接处理不提升,那么a-a0 = 4-65530 = −65526 = 10(在无符号整数运算中,结果的溢出遵循模2的16次方回绕规则)



2. 移植到32位单片机,不能正常运行


    故障描述:在a++溢出返回0后,程序异常;
    原因分析:(a-a0)提升为32位有符号数int,−65526在范围内不会转换,-65526 >= 10不成立;
    解决方案:if((UNIT16)(a-a0) >= 10)

————————————————
版权声明:本文为CSDN博主「汽车芯猿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dangpu/article/details/158740122

评论

用自加/自减指令代替普通赋值,用查表法代替重复计算  发表于 2026-6-18 10:33
tpgf 发表于 2026-6-18 10:33 | 显示全部楼层
单片机程序中的数据溢出陷阱隐蔽性强,需从代码编写、内存管理、硬件选型等多维度防范
故意相遇 发表于 2026-6-18 14:16 | 显示全部楼层
确实,数据溢出是单片机编程中一个常见的问题,特别是在处理数值较大或者需要精确控制数值范围的场景下。
nomomy 发表于 2026-7-3 22:48 | 显示全部楼层
缓冲区溢出如何影响硬件安全?              
tabmone 发表于 2026-7-4 21:40 | 显示全部楼层
数组和指针越界在单片机中不仅导致数据错误,更可能破坏栈帧、修改关键寄存器或导致程序跑飞。
cemaj 发表于 2026-7-4 22:26 | 显示全部楼层
缓冲区越界              
dspmana 发表于 2026-7-4 22:48 | 显示全部楼层
隐式类型转换引发的计算溢出              
juliestephen 发表于 2026-7-5 10:10 | 显示全部楼层
运算时小类型自动提升为 int,赋值回小变量瞬间溢出,完全隐藏。
eefas 发表于 2026-7-5 11:47 | 显示全部楼层
C 标准规定unsigned 类型溢出是取模回绕,无警告,编译器不会报错。
geraldbetty 发表于 2026-7-5 12:54 | 显示全部楼层
单片机RAM有限,栈空间通常由链接脚本静态分配。
benjaminka 发表于 2026-7-5 14:23 | 显示全部楼层
当程序中定义的数组大小小于实际访问的元素个数时,就会发生数组越界。
lzmm 发表于 2026-7-5 16:46 | 显示全部楼层
堆栈被破坏,函数返回地址篡改,程序跑飞、看门狗复位
burgessmaggie 发表于 2026-7-5 20:41 | 显示全部楼层
无编译警告、无硬件报错,程序不崩溃但逻辑错乱
ingramward 发表于 2026-7-6 21:01 | 显示全部楼层
如何检测单片机中的算术溢出?              
pixhw 发表于 2026-7-7 09:23 | 显示全部楼层
在资源受限系统中优先使用静态内存分配,若必须使用动态分配,应实现内存池管理并设置分配上限。
gygp 发表于 2026-7-8 16:27 | 显示全部楼层
单片机的栈空间通常很小。局部变量存储在栈上,数组越界写入会覆盖相邻的变量甚至返回地址。
louliana 发表于 2026-7-12 21:38 | 显示全部楼层
数组循环严格限制下标范围,禁止用 char 做长循环下标
wengh2016 发表于 2026-7-15 18:34 | 显示全部楼层
signed char / int 溢出属于Undefined Behavior,不同编译器、不同优化等级行为不一样
lzbf 发表于 2026-7-16 13:22 | 显示全部楼层
堆栈溢出在单片机系统中极为常见,其诱因包括递归调用深度过大、局部变量数组分配过大,或中断嵌套过深。
wangdezhi 发表于 2026-7-16 15:25 | 显示全部楼层
在资源受限的单片机中,频繁使用动态内存分配极易导致内存碎片或耗尽。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

166

主题

583

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部
0