自实现FLASH读取函数中的隐式类型转换bug踩坑记录

问题现象及背景

在自行封装FLASH自用库的过程中,测试读取 API 时发现了一个隐藏Bug.

cpp 复制代码
#define FLASH_BYTES_PER_PAGE (1024UL)   // 无符号常量
bool Cus_Flash_ReadOutPage( uint32_t PageAddress, uint8_t *pOutBuffer, int32_t Size )
{

.............

   if ( (Size - FLASH_BYTES_PER_PAGE) > 0 )    // 缓冲区给大了,已经读完一页了,剩下空间以0填充.
     {
       memset(&pOutBuffer[FLASH_BYTES_PER_PAGE], 0, (Size - FLASH_BYTES_PER_PAGE));
     }

...............

}

(相关 API 问题部分如上)

cpp 复制代码
 uint8_t RxBuf[128] = { 0 }; 
 Cus_Flash_ReadOutPage(Address, RxBuf, sizeof(RxBuf));

(调用示例)

具体问题为:函数调用时当传入的 Size 小于 FLASH_BYTES_PER_PAGE,在经过判断分支后,被判断为true,进而执行memset后触发硬件HardFault。

原因分析

经过调试分析,当有符号整数(intint32_t)与无符号整数(unsigned intuint32_t)进行算术运算(如减法)时,有符号数会被隐式转换为无符号数。如果运算结果本应为负数,则会变成一个很大的正数(无符号下溢),导致后续逻辑判断错误。

cpp 复制代码
uint32_t a = 1024;
int32_t  b = 64;
// b - a 的执行过程:
// 1. b 被转换为 uint32_t,值为 64(无符号)
// 2. 计算 64 - 1024,在无符号算术中结果为 2^32 - 960 = 4294966336
// 3. 这个值大于 0,所以条件永远为真

例如上述当 Size = 64 时,条件本应为假,但由于隐式转换,无符号下溢,条件为真,导致 memset 越界写入大量字节,进而导致HardFault触发。

解决方法

① 通过强制类型转换,将FLASH_BYTES_PER_PAGE转换为(int32_t)形式.

cpp 复制代码
将 if ( (Size - FLASH_BYTES_PER_PAGE) > 0 )   
改为:

    if ( (Size - (int32_t)FLASH_BYTES_PER_PAGE) > 0 )   

② 先赋值给有符号变量再判断.

cpp 复制代码
    int32_t remaining = Size - FLASH_BYTES_PER_PAGE;  
    if (remaining > 0) 
    {
      memset(&pOutBuffer[FLASH_BYTES_PER_PAGE], 0, remaining);
    }

总结

在 C 语言中,要注意有符号数与无符号数的混合运算,应始终确保操作数类型一致,或使用强制转换明确意图。

相关推荐
youyou-06061 小时前
Classic AUTOSAR 中 CAN 协议栈整体架构
mcu·面试·汽车
神仙别闹1 小时前
基于 C++ 实现(控制台)学生成绩管理系统
开发语言·c++
朝发如雪2 小时前
快速掌握单片机基础(3)(PWM)(通信协议基础)(串口通信时序与参数)(电气特性与电平标准)(51单片机UART寄存器配置)(串口应用层协议)
单片机
伞伞悦读2 小时前
【第36期】Python 目录与路径详解:pathlib、文件遍历、创建、复制、移动和删除风险
开发语言·python
智者知已应修善业3 小时前
【4060BD_5V应用电路图】2022-12-24
驱动开发·经验分享·笔记·硬件架构·硬件工程
天空'之城4 小时前
单片机基础核心知识点汇总(四十)
单片机·嵌入式硬件
smartpi_ai4 小时前
离线语音模块误识别问题全面解决方案:命令词设计、防误触与灵敏度调优指南
人工智能·单片机·语音识别
free-elcmacom4 小时前
C语言字符指针与字符串字面量——从一道“剑指 Offer”笔试题说起
c语言·visual studio
LCG元4 小时前
STM32F103 驱动 HX711 称重实战:DOUT 就绪时序、增益切换陷阱与两点标定精度实测
stm32·单片机·嵌入式硬件
染予4 小时前
代码中相关C语言知识点总结
stm32