苏林

一程序, 一世界

用户操作
[即时聊天] [发私信] [加为好友]
苏林ID:Slin000
92020次访问,排名1021(-1)好友86人,关注者97
仔细思考,踏实做事
MSN:hotsoo@hotmail.com
按关键字聊天的小程序,欢迎试用:
http://6t6t.xicp.net
Slin000的文章
原创 33 篇
翻译 0 篇
转载 0 篇
评论 565 篇
苏林的公告

诚邀朋友们试用
10楼聊天室
按关键字聊天,找到有共同话题的人!

欢迎给我留言,谢谢

最近评论
zoubin1986:看见电脑小白几个字我就想发飙!
自己玩过几年开发就当自己成仙了~
听人说过一句话:上海人歧视外地人就像巴黎人瞧不起全世界的人一样~~~~~
劣根性,就懂内讧!就懂划分阶级!你也是打娘胎里出来的,现在反倒看不起“刚出生”的了。

其实大家若都有钱谁又非得用盗版?有需求才会有市场!软件开发者们!是你们拱手将中国让给了微软!怎么就不懂奋起直追,而非……
hjdl60:我就正在看ogre3D真的很精彩!大师就是大师,设计模式的应用,整体框架的构思无不散发着智慧!
lonelybug:你放心,肯定不会。
l_lengqing:Javascript在网页设计中很有威力,
以前没做页面没注意,做了以后才发现用它很好
zabaglione:应该不会成为主流。这种解释型的语言。
文章分类
    收藏
      相册
      友情链接
      爱生活,爱读书--杨福川 图灵
      存档
      订阅我的博客
      XML聚合  FeedSky
      订阅到鲜果
      订阅到Google
      订阅到抓虾
      订阅到BlogLines
      订阅到Yahoo
      订阅到GouGou
      订阅到飞鸽
      订阅到Rojo
      订阅到newsgator
      订阅到netvibes

      原创 Bug分析之0减1到底等于几收藏

      新一篇: “IPv9十进制网络”的忽悠策略 | 旧一篇: 透过宏定义了解MFC的消息响应机制

              0减1等于几?小学生都知道,而计算机却常干傻事。本文介绍一种和数据类型相关的编程Bug,分析Bug现象和产生原理,做为小小的Debug经验与大家分享。 

       

      前几天用VC写了个程序,程序中有个遍历列表的功能。使用vector作为列表的数据结构,用一个整型数CurIndex记录当前记录。当用户点击向前按钮时,CurIndex减1,如果CurIndex已经是第一个元素了,就让CurIndex转向最后一个元素。
       
      变量声明如下:
       
      vector<ItemType> Vector;
      int CurIndex;
       
      在用户点击向前按钮时,调用下面的函数:
      void MovePre()
      {
             
      --CurIndex;
             
      if (CurIndex<0)
                    CurIndex 
      = Vector.size()-1;
      }
       
      这段程序有个问题:当Vector为空是,Vector.size()为0,这时界面显示CurIndex为-1。为了避免CurIndex为-1,把 MovePre的代码改为如下:
            
      void MovePre()
      {
             --CurIndex;
             if (CurIndex<0)
                    CurIndex = max(0, Vector.size()-1); // 这里使用max宏
      }
       
      按预期,当Vector为空时,CurIndex的值应该为0。然而实际结果是CurIndex仍然为-1。单步调试,的确执行了相应的语句,但CurIndex的就是不变的-1,重新编译也没用。这是不是很奇怪呢?
       
      如果Vector.size()-1的结果小于0,那么max(0, Vector.size()-1)的结果就应该是0;
       
      如果Vector.size()-1的结果比0大,那么max(0, Vector.size()-1)的结果就应该是个正整数才对。
       
      然而实际结果确是-1。0减1比0大,并且等于-1?多么矛盾呀!
       
      如果您看了下面的语句,也许就矛塞顿开了:
      int CurIndex = max( 0, (unsigned int)0-1);
       
      您认为CurIndex应该等于几呢?
       
      当0减去1的时候,它的结果化为16进制,应该为0x ff ff ff ff(假设为4字节)。作为有符号整数,它的值为-1。而做为无符号整数,它的值为4294967295(使用Windows自带的计算器算的)。
       
      按C++的隐式类型转换规则:程序在执行算术运算时,低类型向高类型转换。这时(unsigned int)0-1的值为4294967295。显然这个值比0大,所以max( 0, (unsigned int)0-1)的计算结果应该为4294967295,即0x ff ff ff ff,类型为无符号整型(unsigned int)。
       
      当把这个结果赋值给CurIndex时,CurIndex是int型的,使用另一条C++的隐式类型转换规则:在赋值表达式中,右边表达式的值自动隐式转换为左边变量的类型,并赋值给它。0x ff ff ff ff当做整型赋值,结果就是-1。所以CurIndex的值为-1,16进制仍然是0x ff ff ff ff。
       
      vect类的size()函数返回值就是无符号型的,所以CurIndex = max(0, Vector.size()-1)的值可能为-1就不奇怪了。
       
      所以0减1等于几,还得看是什么类型的0,以及什么类型的1。
       
      0-1 == -1;
      (unsigned int)0-1 == 4294967295;
       
      Bug一不小心就跑出来,借用范厨师的话:真是防不胜防呀!
       
      作者:苏林
       

      发表于 @ 2008年01月24日 16:11:00|评论(loading...)|编辑

      新一篇: “IPv9十进制网络”的忽悠策略 | 旧一篇: 透过宏定义了解MFC的消息响应机制

      评论

      #bcdefbver 发表于2008-01-24 17:22:10  IP: 218.249.195.*
      逻辑问题!
      void MovePre()
      {
      --CurIndex;
      if (CurIndex<0)
      CurIndex = Vector.size()-1;
      }



      void MovePre()
      {
      --CurIndex;
      if (CurIndex<0)
      CurIndex = max(0, Vector.size()-1);
      }
      两个函数根本没区别!最后CurIndex 依然会被赋值为0!然后CurIndex --;界面自然显示为-1!
      改为
      void MovePre()
      {
      if(CurIndex>0)
      --CurIndex;
      if (CurIndex<0)
      CurIndex = Vector.size()-1;
      }
      2008-01-24 18:03:47作者回复
      请注意内容:CurIndex = max(0, Vector.size()-1);<br />我使用了max宏 用来确保CurIndex大于0;<br />使用你写的代码,当Vector.size()为0时, 仍会是 -1, 而且当CurIndex==0时, 它将一直为0 .<br />谢谢关注, 我已经在后面的代码上加了注释, 以使大家能注意到两段代码的区别。
      #Slin000 发表于2008-01-24 18:04:49  IP: 210.13.74.*
      请注意内容:CurIndex = max(0, Vector.size()-1);
      我使用了max宏 用来确保CurIndex大于0;
      使用你写的代码,当Vector.size()为0时, 仍会是 -1, 而且当CurIndex==0时, 它将一直为0 .

      谢谢关注, 我已经在后面的代码上加了注释, 以使大家能注意到两段代码的区别。
      #classicwuhao 发表于2008-01-25 04:36:22  IP: 10.6.202.*
      为什么一开始就要用int呢?

      unsigned int CurIndex;
      CurIndex=(CurIndex) ? --CurIndex : Vector.size();

      #Slin000 发表于2008-01-25 09:45:38  IP: 210.13.74.*
      回复classicwuhao
      为什么要用int呢? 因为是个Bug嘛, 不过就算不用int, 这个Bug也依然存在.

      对于你的这一句, 同样也有个Bug, CurIndex指示不到数组的最后一个元素,请仔细看看。

      还是范厨师的话: 真是防不胜防呀。
      #sheds 发表于2008-01-25 12:17:59  IP: 116.30.105.*
      理论有问题,咋 写都是错的
      #redraiment 发表于2008-01-25 13:46:29  IP: 220.190.71.*
      在原来的代码再加个判断。也许可以。
      void MovePre()
      {
      --CurIndex;
      if (CurIndex<0)
      CurIndex = Vector.size()-1;
      }

      void MovePre()
      {
      --CurIndex;
      if (CurIndex<0)
      CurIndex = Vector.size()-1;
      if (CurIndex<0)
      CurIndex = 0;
      }
      #lonegunman 发表于2008-01-25 17:24:30  IP: 222.66.117.*
      说的有道理,呵呵。不过如果是我的话,我可能会这么写:
      CurIndex = (Vector.size() == 0) ? 0 : (CurIndex + Vector.size() - 1) % Vector.size();
      手头没有装vc,不知道这么写对不对。。。
      2008-01-29 09:15:25作者回复
      当Vector为空时,会出现除0错误
      #minl 发表于2008-01-25 19:00:11  IP: 207.46.55.*
      这么一篇简简单单的assigning a minus number to unsigned integral object, which in this case is size_type竟然费了这么大劲解释和所谓“调试”,竟然还上了csdn首页并加粗!我十分悲哀!
      2008-01-29 09:11:57作者回复
      很多Bug都出在简单的东西上,别看问题简单,它一样能让程序出错。<br />这个程序中的错误是不容易发现的,因为程序的代码看起来很正确,而编译器报的类型不匹配的Warning也很多。<br />如果您有更高深的东西,希望也写出来,我想很多人和我一样,非常乐意分享。
      #茂源 发表于2008-01-26 20:46:05  IP: 119.4.26.*
      谈一谈个人看法:
      首先,CurIndex 的初始化问题应该为,当Vector没有数据时,应该为一个非法的值,可以表示为-1,这个时候诸如前后移动的操作都为无效。

      当Vector有数据时,CurIndex 的计算应该为:
      向前移动: CurIndex = ((CurIndex -1) + VectorSize) % VectorSize;
      向后移动:CurIndex = ((CurIndex +1) + VectorSize) % VectorSize;

      #茂源 发表于2008-01-26 20:47:35  IP: 119.4.26.*
      向后移动:CurIndex = (CurIndex +1) % VectorSize;
      搞错了一点,向前移动,需要+VectorSize 以确保其为正数,取模才能正确,向后移动,必定为正数。
      #Ajampie 发表于2008-01-27 21:13:18  IP: 222.134.93.*
      我认为写东西的时候没有注意编译器的问题,,还有就是。。。。。我也不知道怎么写了。昨天刚看了一点,今天就忘记怎么说了。。新手。。
      #flairpower 发表于2008-01-29 13:46:56  IP: 211.94.163.*
      void MovePre()
      {
      if (CurIndex!=0)
      --CurIndex;
      else
      CurIndex = 0;
      }
      #lonegunman 发表于2008-01-30 23:57:04  IP: 61.173.29.*
      “说的有道理,呵呵。不过如果是我的话,我可能会这么写:
      CurIndex = (Vector.size() == 0) ? 0 : (CurIndex + Vector.size() - 1) % Vector.size();
      手头没有装vc,不知道这么写对不对。。。

      2008-01-29 09:15:25作者回复:
      当Vector为空时,会出现除0错误

      呵呵,您说的对,我也是看您的代码中没有对Vector是否为空的监测,按防御性编程的原则是要首先判断的。
      #yang79tao 发表于2008-02-01 13:55:57  IP: 219.135.146.*
      0 - 1 和
      (unsigned int) 0 - 1
      当然是不同的了,这有什么好争论的?
      #yang79tao 发表于2008-02-01 14:04:13  IP: 219.135.146.*
      相当于max((unsigned int) -1, 0),结果当然是(unsigned int) -1大,但又将(unsigned int) -1赋给一个int值,所经结果又变成-1了。
      #yueguangbuxiu 发表于2008-07-30 17:10:52  IP: 192.168.0.*
      战略决定战术的难易程度,从此可以看得出楼主是一个智力平庸的人。
      这显然就是一个典型的环形队列问题,你在一头做判断,岂有不出错的道理。
      这么简单的一个问题,居然把它当作技术来炫耀,实在有点遗笑大方啊!!以后搞点难的问题来。
      发表评论  


      登录
      Csdn Blog version 3.1a
      Copyright © 苏林