当前位置:网站首页>float 与 int 相乘产生的令人崩溃的“ 2.3 * 10 = 22 ”
float 与 int 相乘产生的令人崩溃的“ 2.3 * 10 = 22 ”
2022-06-29 09:10:00 【水似冰】
越是简单的越不能忽视
类型强转一定要 注意! 注意! 注意!
以上两天结论前前后后花了我三天工作时间才让我意识到并学到。
有的时候,不管你小心还是无意,坑就在那里,踩的人够多,也许就填平了。
在工作中,分配到一个bug,简单描述一下:该程序很庞大,由QT编写,跨平台,支持ubuntu和windows,其中一个模块需要控制海康摄像头,代码中有海康的SDK。bug的现象是无法设定到指定的摄像头调焦倍数与焦距,表现就是摄像头模糊不清,无法正常拍摄,且只在windows下发生。
本文由以下部分组成:
- 调试步骤
- SDK验证
- 2.3 * 10 = 22
调试步骤
工程代码缺陷
bug刚刚拿到手,看了遍代码,一个显而易见的缺陷暴露出来:
- 开环式代码
什么是开环式代码?
简单来看,这部分代码就是这样的:
缺陷有3:
- 没判断设定值是否合法
- 没检查设置是否成功
- 没有防御机制,没有给出设置失败的处理办法
于是添加:
- 合法性检查
- 开定时循环检查
- 定时器中检查不成功重设
疑似SDK缺陷
同样的代码,在不同的系统中表现不同。
ubuntu 14.04 : 正常
windows7 : **异常 **
采用排除法,代码中逻辑处理都是一致的,唯一不同的就是海康的sdk,一个是linux64版本,一个是win32版本。
运行时一个加载.so库,一个加载dll。
那么就来找找SDK的茬吧
SDK验证
此处略,详见:
2.3 * 10 = 22
查来查去,最终比对自己的验证sdk的demo与工程代码,发现最可疑的就是, 聚焦倍数(zoom值)的处理是有差异,验证demo中直接使用float,而工程代码中会强制转换int,便于显示以及处理,可我恰恰没想到,就这个强制转是问题所在,确切的说,是不同系统下的处理是问题原因所在。
先列出罪魁祸首:zoom = rOpticalZoomLevelP * 10;
再来看一下其中变量的声明与定义:int zoom;float rOpticalZoomLevelP = 0.0f;
使用qDebug()打印发现:rOpticalZoomLevelP*10之前rOpticalZoomLevelP值是2.3
而在之后强转赋值给zoom后,zoom是22。
也就是说:2.3 * 10 = 22???
ubuntu下
系统:ubuntu16.04
gcc版本:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10)
demo:
int main(int argc, char **argv)
{
float a = 2.3f;
int b =0;
b = a*10;
printf("b ------>%d\n",b);
return 0;
}
result:
windows7下
系统:windows7
gcc版本:MinGW 4.9.1 32bit MinGW
demo:
int main(int argc, char **argv)
{
float a = 2.3f;
int b =0;
b = a*10;
printf("b ------>%d\n",b);
return 0;
}
result:b -------> 22
问题原因暂时未知,但是可以规避,使用qRound()函数:
zoom = qRound(qreal(rOpticalZoomLevelP*10))
原因
为什么会出现这样的情况呢,因为 a 是一个float型的数据,我们看它是2.3,但是它在内存里就不一定是2.3,它可以是2.29999999999999999,或者2.30000000000000001,因为浮点型的范围为-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38;
边栏推荐
- InvalidConnectionAttributeException异常处理
- 1.4 regression of machine learning methods
- Could not open JDBC connection for transaction
- 动态规划总结
- The 23 most useful elasticsearch search techniques you must know
- Construction and use of Changan chain go language smart contract environment
- KiCad学习笔记--快捷键
- Fabrication d'une calculatrice d'addition simple basée sur pyqt5 et Qt Designer
- Student增删gaih
- 你知道BFD是什么吗?一文详解BFD协议原理及使用场景
猜你喜欢

Automatic 3D Detection and Segmentation of Head and Neck Cancer from MRI Data.

The principle of session and cookie

Kicad learning notes - shortcut keys

Data visualization: the four quadrants of data visualization teach you to correctly apply icons

Self cultivation (XXI) servlet life cycle, service method source code analysis, thread safety issues

Install and configure redis in the Linux environment, and set the boot auto start

长安链数据存储介绍及Mysql存储环境搭建

Segmentation of Head and Neck Tumours Using Modified U-net

Have you done the network security "physical examination" this year?

Simplicity studio does not recognize the new JLINK V9 solution
随机推荐
监控数据源连接池使用情况
【技术开发】酒精测试仪解决方案开发设计
通用分页框架
数据可视化:数据可视化的意义
数据治理:元数据管理(第二篇)
指针函数和函数指针
Closed door cultivation (24) shallow understanding of cross domain problems
Fully Automated Gross Tumor Volume Delineation From PET in Head and Neck Cancer Using Deep Learning
Simplicity studio does not recognize the new JLINK V9 solution
数据库常见面试题(附答案)
装饰器模式的应用,包装ServletRequest,增加addParameter方法
IDEA调试失败,报JDWP No transports initialized, jvmtiError=AGENT_ERROR_TRANSPORT_LOAD(196)
LC236. 二叉树的最近公共祖先
【NOI模拟赛】为NOI加点料(重链剖分,线段树)
Surveiller l'utilisation du pool de connexion des sources de données
After aikuai is installed or reset, the PC or mobile terminal cannot obtain IP
Idea auto completion
InvalidConnectionAttributeException异常处理
User level threads and kernel level threads
Self cultivation (XXI) servlet life cycle, service method source code analysis, thread safety issues