发现C++Builder 2010一组类BUG
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的更多相关文章
- c++ builder 2010 错误 F1004 Internal compiler error at 0x9740d99 with base 0x9
今天遇到一个奇怪的问题,拷贝项目后,在修改,会出现F1004 Internal compiler error at 0x9740d99 with base 0x9 ,不管怎么改,删除改动,都没用,关闭 ...
- Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析
前言 前些天,测试MM发现了一个比较奇怪的bug. 具体表现是: 1.将app包通过电脑QQ传送到手机QQ上面,点击安装,安装后选择打开app (此间的应用逻辑应该是要触发 [闪屏页Activity] ...
- 【转载】Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析
前言 前些天,测试MM发现了一个比较奇怪的bug. 具体表现是: 1.将app包通过电脑QQ传送到手机QQ上面,点击安装,安装后选择打开app (此间的应用逻辑应该是要触发 [闪屏页Activity] ...
- 使用iskindofclass来发现对象是否是某类或其子类的实例
发现对象是否是特定类或其子类的实例 要发现对象是否是某类或其子类的实例,请在对象上调用 isKindOfClass: 方法.当应用程序需要发现其响应的消息(实现的或继承的),它有时进行以上的检查. s ...
- c++builder 读写文件类
c++builder 读写文件类 TStreamReader.TStreamWriter读取一行 http://docwiki.embarcadero.com/CodeExamples/XE8/en/ ...
- 0422 发现( 数学口袋精灵)bug
团队博客地址: 甘佳萍:http://www.cnblogs.com/gjpg/ 李鹏飞:http://www.cnblogs.com/l549023320/ 赵创佳:http://www.cnblo ...
- 发现一个c++ vector sort的bug
在开发中遇到一个非常诡异的问题:我用vector存储了一组数据,然后调用sort方法,利用自定义的排序函数进行排序,但是一直都会段错误,在排序函数中打印参加排序的值,发现有空值,而且每次都跟同一个数据 ...
- 发现了一个entity framework的BUG
小弟学浅才疏可能是小题大做,但遇上了并且让我麻烦了一阵,就值得记下来 BUG的过程就是我在建立实体模型的时候 命名了一个叫system的实体模型 导致了所有生成类中 引用using system失败
- 发现javax.xml.parsers.SAXParser有bug
javax.xml.parsers.SAXParser有bug, 我发现的地方在characters(char[] ch, int start, int length) length偶尔会变小,导致截 ...
随机推荐
- Swift - 文件,文件夹操作大全
ios开发经常会遇到读文件,写文件等,对文件和文件夹的操作,这时就可以使用NSFileManager,NSFileHandle等类来实现. 下面总结了各种常用的操作: 1,遍历一个目录下的所有文件 1 ...
- select value from v$diag_info where name='Default Trace File';
VALUE -------------------------------------------------------------------------------- /u01/diag/rdb ...
- Threejs 的场景查看 - 几个交互事件库助你方便查看场景
Threejs 的场景查看 - 几个交互事件库助你方便查看场景 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&q ...
- 非常不错的android应用开发详解在安卓开发中
我们在苹果开发中,总会看到XCode,Interface Builder,Object-c这如此入耳入随的单词,但往往多数人在认为XCODE看着简单,InterfaceBuilder好似操作, 而Ob ...
- Rudiments 0.42 发布,C++ 常用工具包 - 开源中国社区
Rudiments 0.42 发布,C++ 常用工具包 - 开源中国社区 Rudiments 0.42 发布,C++ 常用工具包
- 为什么 string.find()返回值是-1
之前好像在哪里见到过这个问题,时间有点久,想不起来了,今天写字符串又碰到这个问题,书上给出的定义是当string.find()没有找到时返回的是一个非常大的值,网上有人说是-1,两种说法都对,由于整数 ...
- API拾遗录之Fragment
Fragment必须内嵌到activity中,它不能单独使用,并且它的生命周期受到activity生命周期的制约——当activity暂停时,所有的fragment暂停,当activity停止时,所有 ...
- java nio-理解同步、异步,阻塞和非阻塞
理解同步.异步,阻塞和非阻塞 结论:阻塞.非阻塞与是否同步异步无关. 转自知乎 “阻塞”与"非阻塞"与"同步"与“异步"不能简单的从字面理解, ...
- jQuery Mobile 是创建移动 web 应用程序的框架。
jQuery Mobile jQuery Mobile 是创建移动 web 应用程序的框架. jQuery Mobile 适用于所有流行的智能手机和平板电脑. jQuery Mobile 使用 HTM ...
- 华为C8816电信版ROOT过程
华为C8816电信版ROOT方法, 网上的方法都不太靠谱.. 昨天弄了好久, 最终搞定.. 整理了一下.. 实用到的就方便多了. <方法不再啰嗦, 都有说明> 1. 获取手机解锁passw ...