频道栏目
首页 > 程序开发 > 软件开发 > C++ > 正文
发现C++Builder 2010集合类的一个BUG
2014-07-03 10:57:48         来源:发现C++Builder 2010集合类的一个BUG  
收藏   我要投稿
今天用C++Builder 2010写一段小代码,用到了集合类,可集合运算结果怎么也不对,排除了其它原因,最后确定应该是集合类源代码的问题,下面是一段集合类的测试代码:
enum TTest{tt0, tt15 = 15, tt16 = 16};
typedef Set TTests;

void __fastcall TForm1::Button1Click(TObject *Sender)
{
	TTests t1 = TTests() << tt15;
	TTests t2 = TTests() << tt16;

	ShowMessage(t1.ToInt());	// 32768
	ShowMessage(t2.ToInt());	// 16777216
}

测试代码中的集合类变量t1,t2分别定义为第15位和第16位,显示结果应该分别为32768和65536,t1结果32768是正确的,t2显示却为16777216,显然是错误的。

接下来,我用Delphi 2010写了类似的测试代码:

type
  TTest = (tt0, tt15 = 15, tt16 = 16);
  TTests = set of TTest;

procedure TForm1.Button1Click(Sender: TObject);
var
  t1, t2: TTests;
begin
  t1 := [tt15];
  t2 := [tt16];
  ShowMessage(IntToStr(LongWord(t1)));  // 32768
  ShowMessage(IntToStr(LongWord(t2)));  // 65536
end;

而Delphi 2010代码显示结果完全正确。

很明显,C++Builder 2010代码中的集合类变量t2向左多移了8位,即16777216是第24位置位后的结果。

我调出C++Builder 2010集合类源代码文件sysset.h,查看了一下其ToInt函数,发现问题就出在这里,请看源码中数据定义和ToInt函数代码:

  template
  class RTL_DELPHIRETURN SetBase
  {
  protected:
    unsigned char Data[((((int)(maxEl/8))-((int)(minEl/8))+1) != 3)?
       (((int)(maxEl/8))-((int)(minEl/8))+1): 4];
  };

  template
  class RTL_DELPHIRETURN Set : SetBase
  {

    ......

    int __fastcall ToInt(void) const
    {
  #pragma option push -w-inl
    int Result = 0;
    for (int i = sizeof(Data)-1; i >= 0; i--)
    {
      Result |= Data[i];
      Result <<= (i * sizeof(unsigned char) * 8);
    }
    return Result;
  #pragma option pop
    }

    ......

  };


上面测试用的集合类TTests最小成员值=0,最大成员值=16,按源码数据长度定义公式计算得3,Byte类型的数组Data长度=4,测试代码中的集合类变量t1和t2的数据分别为"\0\x80\0\0"和"\0\0\1\0",在ToInt函数转换时,t1的有效起始下标i=1,Result赋值0x80后共左移了2次8位,结果为0x8000(32768);而t2的有效起始下标i=2,Result赋值1后左移了3次共24位(即2 * 1 * 8 = 16,1 * 1 * 8 = 8,0 * 1 * 8 = 0),结果为0x1000000(16777216)。

可以将源码中ToInt函数做如下修改:

    int __fastcall ToInt(void) const
    {
  #pragma option push -w-inl
    int Result = 0;
    for (int i = sizeof(Data)-1; i >= 0; i--)
    {
      Result |= Data[i];
      if (i)
          Result <<= (sizeof(unsigned char) * 8);
    }
    return Result;
  #pragma option pop
    }


我只查看了C++Builder 2010,而且也只涉及ToInt函数,其它版本或函数有无问题不清楚,显然这个BUG在程序中有可能是致命的,望各位C++Builder程序员警惕。


点击复制链接 与好友分享!回本站首页
相关TAG标签
上一篇:ajaxFileUpload+struts2实现多文件上传
下一篇:uva 10622 - Perfect P-th Powers(数论)
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站