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

发现C++Builder 2010一组类BUG的更多相关文章

  1. c++ builder 2010 错误 F1004 Internal compiler error at 0x9740d99 with base 0x9

    今天遇到一个奇怪的问题,拷贝项目后,在修改,会出现F1004 Internal compiler error at 0x9740d99 with base 0x9 ,不管怎么改,删除改动,都没用,关闭 ...

  2. Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析

    前言 前些天,测试MM发现了一个比较奇怪的bug. 具体表现是: 1.将app包通过电脑QQ传送到手机QQ上面,点击安装,安装后选择打开app (此间的应用逻辑应该是要触发 [闪屏页Activity] ...

  3. 【转载】Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析

    前言 前些天,测试MM发现了一个比较奇怪的bug. 具体表现是: 1.将app包通过电脑QQ传送到手机QQ上面,点击安装,安装后选择打开app (此间的应用逻辑应该是要触发 [闪屏页Activity] ...

  4. 使用iskindofclass来发现对象是否是某类或其子类的实例

    发现对象是否是特定类或其子类的实例 要发现对象是否是某类或其子类的实例,请在对象上调用 isKindOfClass: 方法.当应用程序需要发现其响应的消息(实现的或继承的),它有时进行以上的检查. s ...

  5. c++builder 读写文件类

    c++builder 读写文件类 TStreamReader.TStreamWriter读取一行 http://docwiki.embarcadero.com/CodeExamples/XE8/en/ ...

  6. 0422 发现( 数学口袋精灵)bug

    团队博客地址: 甘佳萍:http://www.cnblogs.com/gjpg/ 李鹏飞:http://www.cnblogs.com/l549023320/ 赵创佳:http://www.cnblo ...

  7. 发现一个c++ vector sort的bug

    在开发中遇到一个非常诡异的问题:我用vector存储了一组数据,然后调用sort方法,利用自定义的排序函数进行排序,但是一直都会段错误,在排序函数中打印参加排序的值,发现有空值,而且每次都跟同一个数据 ...

  8. 发现了一个entity framework的BUG

    小弟学浅才疏可能是小题大做,但遇上了并且让我麻烦了一阵,就值得记下来 BUG的过程就是我在建立实体模型的时候 命名了一个叫system的实体模型 导致了所有生成类中 引用using system失败

  9. 发现javax.xml.parsers.SAXParser有bug

    javax.xml.parsers.SAXParser有bug, 我发现的地方在characters(char[] ch, int start, int length) length偶尔会变小,导致截 ...

随机推荐

  1. Swift - 使用网格(UICollectionView)的自定义布局实现复杂页面

    网格UICollectionView除了使用流布局,还可以使用自定义布局.实现自定义布局需要继承UICollectionViewLayout,同时还要重载下面的三个方法: 1 2 3 4 5 6 7 ...

  2. hadoop format过程

    private static boolean format(Configuration conf, boolean isConfirmationNeeded ) throws IOException ...

  3. Eclipse添加和查看书签

    添加书签: 在编辑框左边栏右击 > Add Bookmark > 编辑书签名称(可以直接使用默认名称)> OK 查看书签: Window > Show View > Ot ...

  4. visio ppt axure AI svg powerdesign xmind

    visio  ppt  axure  AI svg powerdesign xmind

  5. 基于Chrome开源提取的界面开发框架开篇--转

    初衷 一直希望VC开发者能够方便的开发出细腻高品质的用户界面.我喜欢C++,选择的平台是Windows,所以大部分时间用VC.我自身不排斥其他技术或者开发语言或者开发工具,都去了解,了解的目的是想吸取 ...

  6. 怎样在Android实现桌面清理内存简单Widget小控件

    怎样在Android实现桌面清理内存简单Widget小控件 我们常常会看到类似于360.金山手机卫士一类的软件会带一个widget小控件,显示在桌面上,上面会显示现有内存大小,然后会带一个按键功能来一 ...

  7. java定义和实现接口

    1.定义接口     使用interface来定义一个接口.接口定义同类的定义类似,也是分为接口的声明和接口体.当中接口体由常量定义和方法定义两部分组成.定义接口的基本格式例如以下: [修饰符] in ...

  8. codeforces 604B More Cowbell

    题目链接:http://codeforces.com/contest/604/problem/B 题意:n个数字,k个盒子,把n个数放入k个盒子中,每个盒子最多只能放两个数字,问盒子容量的最小值是多少 ...

  9. 各种oracle10g下载地址(官网网页上好像找不到了)

    Oracle Database 10g Release 2 (10.2.0.1.0) Enterprise/Standard Edition for Microsoft Windows (32-bit ...

  10. deque,list,queue,priority_queue

    1.deque deque双端队列容器与vector一样,采用线性表顺序存储结构,但与vector唯一不同的是,deque采用分块的线性存储结构来存 储数据,每块的大小一般为512字节,称为一个deq ...