使用 cJSON 解析超范围整数导致的 CRC 校验失败分析

在进行CRC校验时,由于cJSON结构体中的intvalueint字段只能存储到(2^31)-1,导致上位机传递的大于此值的数字无法正确存储,从而每次校验得到固定值2147483647。为解决此问题,建议将uf->Crc的赋值由Crc->valueint改为(CRC)->valuedouble,以适应更大范围的数值。

使用 cJSON 解析超范围整数导致的 CRC 校验失败分析

问题现象

在文件下发过程中,发现 CRC 校验始终不通过,并且每次解析得到的 CRC 值都是固定的 2147483647。这个现象明显不符合预期,因为正常的 CRC 值应该是根据文件内容计算得出的变化值。

问题定位

通过调试发现,问题出在使用 cJSON 解析 CRC 值的过程中。让我们先看看 cJSON 的核心结构体定义:

typedef struct cJSON
{
    struct cJSON *next;
    struct cJSON *prev;
    struct cJSON *child;

    int type;
    char *valuestring;
    int valueint;       /* 已废弃的整型字段 */
    double valuedouble; /* 数值类型字段 */
    int decimal_places;
    char *string;
} cJSON;

数据类型限制

在 32 位系统中:

  • int 类型是有符号的 32 位整数
  • 取值范围:-2,147,483,648 ~ 2,147,483,647
  • 最大正数值:2,147,483,647 (0x7FFFFFFF)

问题原因

  1. 上位机下发的 CRC 值为:2,353,641,486
  2. 这个值超出了 int 类型的最大值 2,147,483,647
  3. 当使用 valueint 获取这个值时,由于超出范围,会被截断为 int 类型的最大值
  4. 导致每次获取到的都是固定值 2,147,483,647

解决方案

代码修改

原代码:

uf->Crc = Crc->valueint;  // 使用已废弃的 valueint 字段

修改后:

uf->Crc = (unsigned int)Crc->valuedouble;  // 使用 valuedouble 并转换为无符号整型

修改说明

  1. 使用 valuedouble 字段

    • double 类型可以精确表示大得多的整数值
    • 不会发生数值截断
  2. 类型转换

    • double 转换为 unsigned int
    • unsigned int 的范围是 0 ~ 4,294,967,295
    • 足够容纳我们的 CRC 值 2,353,641,486

验证结果

修改后,CRC 校验开始正常工作:

  1. CRC 值不再是固定的 2,147,483,647
  2. 能够正确获取上位机下发的 CRC 值
  3. 文件校验结果符合预期

经验总结

注意事项

  1. 在处理大数值时,要特别注意数据类型的范围限制
  2. 使用 cJSON 时,优先使用 valuedouble 而不是已废弃的 valueint
  3. 根据实际需求选择合适的数据类型,必要时进行安全的类型转换

最佳实践

  1. 对于可能超出 int 范围的数值,使用 unsigned int 或更大范围的类型
  2. 在进行类型转换时,确保目标类型能够容纳源数据
  3. 在处理 JSON 数据时,注意检查数值范围和类型匹配

参考资料

  • cJSON 文档:cJSON GitHub
  • C 语言数据类型范围
  • JSON 数值处理最佳实践
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值