关于超出表示范围的数据类型转化

发布于:2024-04-20 ⋅ 阅读:(20) ⋅ 点赞:(0)

目录

背景:

问题分析:

参数异常分析:

分析文件原始值:

分析数据类型转换

代码分析:

结论:

参考资料:


背景:

在Ubuntu环境下进行项目开发时,调试时程序总是进入断言错误,但是在Windows环境下,没有出现该错误。起初以为是不同编译器的容错能力不同,应该是产生断言代码兼容性较差导致,但通过仔细分析,发现之前推论较为武断,不是一个科学的问题定位方法,想当然尔。事情发展总是遵循相同规律,就像海因里希法则所指出的:一个明显错误的背后,总是一系列小的错误导致。

问题分析:

传入参数值为-2147483648,即INT32_MIN。

当参数为INT32_MIN时,进入断言。

参数异常分析:

经过逐层调用分析,发现数据从文件提取时,获取的数值已经异常。

查看从文件中获取的原始值

发现从文件中获取的信号值为:4291895296,与m_LH_Line_First_C2_asl :-2147483648不一致。

分析文件原始值:

文件中原始值为-3072000,与以上值都不匹配。

将-3072000 转化为十六进制数字为:0xFFD12000。将4291895296 转为十六进制为0xFFD12000。由此可得,m_LH_Line_First_C2_asl._0_ 信号值获取地址是正确的,但是符号位转化存在问题。

分析数据类型转换

有图可知,在Ubuntu系统中,uint32数据转化为long类型数据时,由于两种数据类型可表示范围不同,因此,出现了非预期结果。同时,在Windows系统中进行验证,由于long类型数据在Windows下占用4个字节,因此将能够获取期望结果。

浮点数 --> 整数

    1. 首先,忽略前者的小数部分
    2. 如果忽略后的值可以由后者表示,直接表示即可
    3. 如果忽略后的值超出了后者所能表示的范围,则是未定义的行为

另外,在为了提高代码的稳定性和健壮性,特别是对快平台数据解析和组装,避免使用数据类型长度不一致数据类型。对于产品代码,使用产品定义数据类型,对于工具代码,建议使用C++ 11标准类型:

代码分析:

原始错误代码

由于long 类型数据长度在不同平台下所表示范围不同,当long类型数据占用8个字节时导致有符号数据被转化为无符号结果

修改后结果:

结论:

程序在ubuntu环境下进入断言,主要由以下几个因素引起:

  • 代码解析时,使用long 型变量存储int32_t类型数据,由于long 类型数据长度在不同平台下所表示范围不同,当long类型数据占用8个字节时导致有符号数据被转化为无符号数值。
  • 由于int32_t类型 接收到超出范围数据时,直接使用numeric_limits<unsigned int>::min()进行赋值,出现未定义行为。
  • 在fabs函数中,进行断言判断时,正好与numeric_limits<unsigned int>::min()进行比较。

以上各种情况组合到一起,从而导致了断言的发生。

因此,在调试过程中出现的问题,我们不能够想当然尔,而是应该静下来仔细分析,找到出现问题的根本原因,这才是对待产品开发应该持有的态度。

参考资料:

安全验证 - 知乎