忽视数值类型的长度范围而造成的问题代码


声明:本文转载自https://my.oschina.net/yhcocacoder/blog/3121362,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

在日常编程中,我们可能经常简单的处理不同数值类型,而忽视其能表示的长度范围,比如int和long,我们可能经常将这两种类型混用,然后遇到编译报错,就用强制转换来应付。但通过我最近遇到的两个代码所暴露出的问题,发现这种做法是不严谨的。

首先看代码1(java代码),某广泛使用的即时通讯SDK所声明的接口

    // 返回第i个元素
	public TIMElem getElement(int i) {
	   // 实现代码省略
    }

	// 返回元素的个数
    public long getElementCount() {
	   // 实现代码省略
    }



这段代码的问题在于:取元素时下标的数值范围和元素数组的长度不一致,我们知道在java中,int表示的范围是-2^31~2^31-1,long的范围式-2^63~2^63-1,那么如果元素个数大于int能表示的最大值,则 getElement是无法取到所有的元素的。那么sdk的demo是怎么使用这个接口的呢?

       List<MessageInfo> list = new ArrayList<>();
        for (int i = 0; i < timMessage.getElementCount(); i++) {
            final MessageInfo msgInfo = new MessageInfo();
            if (ele2MessageInfo(msgInfo, timMessage, timMessage.getElement(i), isGroup) != null) {
                list.add(msgInfo);
            }
        }




这段代码的问题在于,如果getElementCount()的值大于int的最大值,即2^31-1(虽然实际情况不可能出现这样的场景),则getElement的参数会为负数,很可能造成异常。

再看看第二个问题的代码,也是java代码

   class XXXItem implements Comparable{
    // 成员变量,long类型
    private long mTime;
	
	public long getTime() {
        return mTime;
    }
	
    // 实现了一个用于比较大小的接口
	@Override
    public int compareTo(@NonNull XXXItem item) {
        return (int) (item.getTime() - this.getTime());
    }
   }




Comparable的用法,熟悉java的人应该都比较清楚。这里的问题就是出在compareTo上,getTime()返回值是long类型,两个long类型相减,并将结果强制转换为int,可能会造成溢出,从而违背该代码的本来初衷。其实java标准库中的Long类已经给出了比较long的方法,,可以直接调用,它实现的也很简洁。

    public final class Long extends Number implements Comparable<Long> {
	    public static int compare(long x, long y) {
        	return (x < y) ? -1 : ((x == y) ? 0 : 1);
    	}
	}




思考

关于溢出造成的不安全代码并不罕见,在《深入理解计算机系统》这本书中的2.3节就有介绍,里面还举例了FreeBSD的代码库中就曾经存在这种存在安全隐患的代码。我觉得出现这种问题的本质还是因为:计算机科学家在设计补码这种数值表示方式时,是允许溢出这种现象存在的,有些程序逻辑甚至需要溢出来实现,但程序员在开发时,忽略了溢出的存在,而仅凭直觉去写代码,从而造成了这种隐患。因此我觉得我们在日常写代码时要注意:

  1. 设计接口时,相同事物返回值的类型要一致。
  2. 不同类型数值进行比较操作或者进行强制转换赋值时,要格外小心,思考是否会有溢出的情况出现。

本文发表于2019年10月24日 12:00
(c)注:本文转载自https://my.oschina.net/yhcocacoder/blog/3121362,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 272 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

一直到现在我才突然明白,我梦寐以求,是真爱和自由。

把爱情留给我身边最真心的姑娘,你陪我歌唱陪我流浪,陪我两败俱伤。

把青春献给身后那座辉煌的都市,为了这个美梦,我们付出着代价。

又是一年五一,祝我们工人阶级劳动节快乐! 今年被困在北京了,离境再入境需要隔离十五天。只能京津冀周边走一走了,想出去玩啊啊啊啊啊~

人活一辈子,不是一年两年。时间是有连续性的,做抉择的时候要多看几步。保持警惕,大丈夫有所为,有所不为。

快捷链接
网站地图
提交友链
Copyright © 2016 - 2020 Cion.
All Rights Reserved.
ICP备案:鲁ICP备19012333号-4.

鲁公网安备 37061302000383号.