DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: 33227
今日帖子: 17
在线用户: 9
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2019/3/5 17:21:55
标题:
Delphi 的Cardinal类型减法运算有bug 浏览:1912
加入我的收藏
楼主: //bug of Cardinal subtraction
procedure TForm1.Button3Click(Sender: TObject);
var
  c1,c2:Cardinal;
  w1,w2:Word;
  vs: TValueSign;
  ix:NativeInt;
  i64:Int64;
begin
  c1 := 1;
  c2 := 2;
  w1 :=1;
  w2 := 2;

  Assert(c1-c2<>-1); //Bug! c1-c2 should be -1
  Assert(w1-w2=-1); //OK, as we expected

  vs := Math.Sign(c1-c2); //will call: function Sign(const AValue: Int64): TValueSign;
  Assert(vs<>-1);//Bug, should be -1

  ix := c1-c2;
  Assert(ix=-1);//ok, as we expedted

  ix := w1-w2;
  Assert(ix=-1);//ok, as we expedted

  i64 := c1-c2;
  Assert(i64<>-1);//Bug!, i64 should equal -1

  i64 := w1-w2;
  Assert(i64=-1);//ok, as we expedted
end;


已经上报EMB: https://quality.embarcadero.com/browse/RSP-23899
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 wang_80919 (Flying Wang) ★☆☆☆☆ -
普通会员
2019/3/5 17:29:41
1楼: 你不认识 正整数吗?回小学重新学一下吧。
不过 后面的 int64 的值,的确应该是 -1

也就是 i64 := c1-c2; 这个,你的确发现了 BUG。
----------------------------------------------
(C)(P)Flying Wang
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2019/3/5 17:37:48
2楼: to wang_80919: 我的测试代码及结论具体哪里有问题可以指出来讨论, 你凭哪点判断出我不认识正整数了?
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 pspice (pspice) ★☆☆☆☆ -
普通会员
2019/3/5 18:41:50
3楼: Cardinal 和 unsigned int 等价,就是非负整数
----------------------------------------------
-
作者:
男 scarlette (Scarlette) ★☆☆☆☆ -
普通会员
2019/3/5 18:44:38
3楼: (UINT32 - UINT32)不做位宽提升的,所以结果还是UINT32,和-1不等价。INT64那个同理。
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2019/3/5 19:19:54
4楼: (UINT32 - UINT32)我觉得是做了位宽提升的, 因为 Math.Sign(c1-c2) 调用的是 Sign(const AValue: Int64)而不是 Sign(const AValue: Integer). 

我的汇编水平有限, 我觉得如果对比一下 ix := c1-c2 与 i64 := c1-c2的汇编代码可能能发现问题.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 keymark (嬲) ▲▲▲△△ -
普通会员
2019/3/5 21:42:15
5楼: 谁用64位测下  我看到10.3改过 win64 整数  出现垃圾值的说明
----------------------------------------------
[alias]  co = clone --recurse-submodules  up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/>http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
男 138soft (138soft) ★☆☆☆☆ -
盒子活跃会员
2019/3/5 23:07:29
6楼: Delphi7下没问题
----------------------------------------------
是你上错了车,还是我下错了站?
作者:
男 aqtata (从一到十) ★☆☆☆☆ -
盒子活跃会员
2019/3/5 23:33:14
7楼: i64 := c1 - c2; 的汇编

sub eax,dword ptr ss:[ebp-C]          | c1 - c2
xor edx,edx          | 0
mov dword ptr ss:[ebp-18],eax          | i64低32bit为 0xFFFFFFFF(也就是c1-c2的结果)
mov dword ptr ss:[ebp-14],edx          | i64高32bit置零
cmp dword ptr ss:[ebp-14],FFFFFFFF      | 验证高32bit是否为0xFFFFFFFF
jne project1.5EB62C          |
cmp dword ptr ss:[ebp-18],FFFFFFFF      | 验证低32bit是否为0xFFFFFFFF
je project1.5EB642          |

最后i64的值就是0x00000000FFFFFFFF = 4294967295

也验证了3楼朋友说的,c1-c2的结果也是32bit,并存入了i64的低32bit中。

另外,assert里的表达式应该是你期望的表达式,应该书写为Assert(i64 = -1)
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2019/3/6 8:38:22
8楼: 综合起来我觉得应该有如下结论:
1. c1-c2 这个运算的结果数据类型, Delphi本意是要当成Int64的(后面分析), 这个运算分成了两步
  1) 执行32的减法,得到FFFFFFFF
  2) 扩展到 64位, 但这一步它做错了,不能简单把高32位置零, 要进行符号位扩展!
2.为什么说Delphi编译器本意是要将c1-c2结果设为Int64呢?有下面两个证据:
  1) Math.Sign(c1-c2) 调用的是 function Sign(const AValue: Int64): TValueSign; 不是 function Sign(const AValue: Integer): TValueSign;
  2) Assert(c1-c2=-1)会失败
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 lordaeron (Terry) ★☆☆☆☆ -
禁用账号
2019/3/6 8:45:36
9楼: ……
被禁用帐号,帖子内容自动屏蔽!
……

----------------------------------------------
该账号是个傻逼
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2019/3/6 8:55:36
10楼: lordaeron 说笑了, 做个商业级的编译器, 真不是简单的事, Delphi当年也是群英璀璨
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 bahamut8348 (leonna) ★☆☆☆☆ -
普通会员
2019/3/6 9:36:41
11楼: 都是一些基础的东西。居然又是汇编又是编译器的。

cardinal本身是无符号整型,无符号和无符号运算,结果必然也是无符号。
虽然二进制都是0xffffffff。你强转一下就成-1了,无非就是对最高位的解释罢了。

对于那个math.sign的调用,回去看看最基本的数据结构不就行了么?
人家一个32位无符号数赋值给一个64位的有符号数,这叫赋值兼容。赋值兼容你们居然会要求人家改变你的数据?

我觉得吧,基础知识真的是相当重要。
----------------------------------------------
--
作者:
男 dmzn (dmzn) ★☆☆☆☆ -
盒子活跃会员
2019/3/6 11:16:05
12楼: Assert(c1-c2<>-1); //c1 - c2的结果默认是一个cardinal变量,值为High(cardinal)

i64 := c1-c2;  //等同于i64=Int64(cardinal),i64的值为High(cardinal)
Assert(i64<>-1);//判定成立
----------------------------------------------
生活愉快.
作者:
男 lfxsq (lfxsq) ★☆☆☆☆ -
普通会员
2019/3/6 11:40:26
13楼: 这个应该算bug
----------------------------------------------
-
作者:
男 lordaeron (Terry) ★☆☆☆☆ -
禁用账号
2019/3/6 11:50:17
14楼: ……
被禁用帐号,帖子内容自动屏蔽!
……

----------------------------------------------
该账号是个傻逼
作者:
男 wang_80919 (Flying Wang) ★☆☆☆☆ -
普通会员
2019/3/6 12:45:21
15楼: 反正 D7 就是个垃圾
XE8 都已经步入 垃圾堆了。
10.3.1 还是挺好用的。
----------------------------------------------
(C)(P)Flying Wang
作者:
男 earthsbest (全能中间件) ▲▲▲▲△ -
普通会员
2019/3/6 12:49:54
15楼: 刚测试的结果:
  ix := c1 - c2;
  //Delphi 7/10.3 64-bit ix = High(Cardinal)=4294967295
  //Delphi 10.3 32-bit  ix = -1;
  //Assert(ix = -1); //ok, as we expedted

  i64 := c1 - c2;
  //Delphi 7/10.3 一样 ix = High(Cardinal)=4294967295
  //Assert(i64 <> -1); //Bug!, i64 should equal -1
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2019/3/6 14:36:08
16楼: Delphi: 10.3.1, 32Bits
OS: Win 7, 32Bits

procedure TForm1.Button5Click(Sender: TObject);
var
  b1,b2:Byte;
  w1,w2:Word;
  c1,c2:Cardinal;
  i64:Int64;
begin
  b1 := 1;
  b2 := 2;
  i64 := b1-b2;
  Assert(i64=-1);//OK

  w1 := 1;
  w2 := 2;
  i64 := w1-w2;
  Assert(i64=-1);//OK

  c1 := 1;
  c2 := 2;
  i64 := c1-c2;
  Assert(i64=-1);//Fail

end;

at least, we expect a coincident result
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行74.21875毫秒 RSS