发现C++Builder 2010一组类BUG

发现C++Builder 2010一组类BUG

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

    今天C++Builder 2010写小码,我们用一个集合类。您可以设置操作结果是不正确的,排除其他原因引起的,最后,它应该被设置以确定问题类的源,以下是一个集合类测试代码:

enum TTest{tt0, tt15 = 15, tt16 = 16};
typedef Set<TTest, tt0, tt16> 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 T, unsigned char minEl, unsigned char maxEl>
  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 T, unsigned char minEl, unsigned char maxEl>
  class RTL_DELPHIRETURN Set : SetBase<T, minEl, maxEl>
  {

    ......

    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程序猿警觉。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116748.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 基于全卷积神经网络的图像分割方法详解(二)

    基于全卷积神经网络的图像分割方法详解(二)最近这段时间刚好忙完学业作业,抽空来总结一下前段时间的工作。前段时间一直忙于用深度学习做医学图像分割,采用的方法是FCN,也就是全卷积神经网络。全卷积神经网络是基于卷积神经网络的改进,使得输入和输出的尺寸一致,并且对每个像素点进行分类,达到图像分割的目的。下图是全卷积神经网络的流程图。其中第一行是提取特征步骤,然后2Xconv7和4Xconv7分别表示对conv7的输出进行2倍和4倍上采样…

  • maven项目打包成war包并在linux下部署到tomact上

    maven项目打包成war包并在linux下部署到tomact上

  • Linux安装gcc的四种方法「建议收藏」

    Linux安装gcc的四种方法「建议收藏」相比于windows系统,Linux安装程序就比较复杂了,很多需要root用户才能安装。常见的有以下几种安装方法 源码安装 rpm包安装 yum安装(RedHat、CentOS) apt-get安装(debian,ubuntu) 源码安装以安装gcc为例,登陆https://gcc.gnu.org/,下载自己想要的版本的gcc安装包上传gcc-4.1.2.tar.gz到Linux服务器任意目录,解压解压目录执行shell命令./configurat.

  • mybatis+springboot+flowable6.4.0遇到的问题[通俗易懂]

    mybatis+springboot+flowable6.4.0遇到的问题[通俗易懂]整合mybatis+springboot+flowable6.4.0遇到的坑前面一大堆都是记录问题过程,爱看不看。解决办法再最后。问题:org.apache.ibatis.binding.BindingException:Invalidboundstatement(notfound)解决办法:就是兼顾flowable和mybatis的配置.完前面一大堆都是记录问题过程,爱看不看。解决…

  • 图片打水印 缩放 和一个输入流的转换

    图片打水印 缩放 和一个输入流的转换

  • 国外企业电子邮箱大全,国外用邮箱哪个好?怎么注册国外邮箱?「建议收藏」

    国外企业电子邮箱大全,国外用邮箱哪个好?怎么注册国外邮箱?「建议收藏」外贸、物流、留学移民等公司都会用到能往国外发邮件的邮箱。在知乎上看到,TOM企业邮箱国内国外都能用,移动办公也方便。国外用邮箱群发邮件群发开发信、给客户群发节日祝福都会企业邮箱的邮件群发功能。用群发单显能起到事半功倍的效果,如下图,登录邮箱后,点击【写邮件】,再点击【群发单显】就能一次几百封的群发邮件了。如何是给公司所有员工群发邮件通知,还是邮件群组更方便。像微信群一样,把所有人拉到一个群组里,往这个组里发通知,群里其他人都能收到,适用于公司内部多部门、跨地区管理沟通。TOM这个国际邮箱之所以用的

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号