大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。
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账号...