使用 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)
问题原因
- 上位机下发的 CRC 值为:2,353,641,486
- 这个值超出了
int类型的最大值 2,147,483,647 - 当使用
valueint获取这个值时,由于超出范围,会被截断为int类型的最大值 - 导致每次获取到的都是固定值 2,147,483,647
解决方案
代码修改
原代码:
uf->Crc = Crc->valueint; // 使用已废弃的 valueint 字段
修改后:
uf->Crc = (unsigned int)Crc->valuedouble; // 使用 valuedouble 并转换为无符号整型
修改说明
-
使用
valuedouble字段double类型可以精确表示大得多的整数值- 不会发生数值截断
-
类型转换
- 将
double转换为unsigned int unsigned int的范围是 0 ~ 4,294,967,295- 足够容纳我们的 CRC 值 2,353,641,486
- 将
验证结果
修改后,CRC 校验开始正常工作:
- CRC 值不再是固定的 2,147,483,647
- 能够正确获取上位机下发的 CRC 值
- 文件校验结果符合预期
经验总结
注意事项
- 在处理大数值时,要特别注意数据类型的范围限制
- 使用 cJSON 时,优先使用
valuedouble而不是已废弃的valueint - 根据实际需求选择合适的数据类型,必要时进行安全的类型转换
最佳实践
- 对于可能超出
int范围的数值,使用unsigned int或更大范围的类型 - 在进行类型转换时,确保目标类型能够容纳源数据
- 在处理 JSON 数据时,注意检查数值范围和类型匹配
参考资料
- cJSON 文档:cJSON GitHub
- C 语言数据类型范围
- JSON 数值处理最佳实践
在进行CRC校验时,由于cJSON结构体中的intvalueint字段只能存储到(2^31)-1,导致上位机传递的大于此值的数字无法正确存储,从而每次校验得到固定值2147483647。为解决此问题,建议将uf->Crc的赋值由Crc->valueint改为(CRC)->valuedouble,以适应更大范围的数值。
3924

被折叠的 条评论
为什么被折叠?



