关于32位计数器溢出问题

好久没写博客了,昨天遇到一个时间计数溢出问题, 做个简单记录吧

背景:底层提供一个unsigned int的变量表示自开机以来累计时间,用作码流的时间戳,单位ms.

问题:32位无符号数的毫秒计数,大概49天就会溢出,溢出后时间计数用作时间戳就会出错,导致无法正确解码。

为解决这一问题,用一个64位变量来保存累计时间,

方法如下:

点击(此处)折叠或打开

  1. unsigned long long ullCurFrmPts=0;//app里用到的时间戳,微秒计
  2. unsigned int bf_stamp=0;
  3. unsigned int timestamp=0;//SDK提供的时间戳

  4. bf_stamp = ullCurFrmPts&0xffffffff);
  5. if(timestamp*1000 < bf_stamp) {
  6.     ullCurFrmPts = (ullCurFrmPts + 1<<32);
  7. }

  8. ullCurFrmPts = (ullCurFrmPts&0xffffffff00000000)+timestamp*1000;

运行,时间怎么都不对

找问题步骤1

先确定32ARM上实现的unsigned long long是否64位?
测试代码

点击(此处)折叠或打开

  1. int num=0;
  2. unsigned long long test=0;
  3.     
  4. test = ~0;
  5. printf("test is %llx\n",test);
  6. num=0;
  7. while(1){
  8.    if(test&0x1){
  9.        num++;
  10.    }
  11.    test = test>>1;
  12.    if (test == 0)break;
  13.        printf("test is %llx\n",test);
  14. }
  15. printf("test is %dbit\n",num);

执行结果如下

点击(此处)折叠或打开

  1. [root@GM]# ./test
  2. test is ffffffffffffffff
  3. test is 7fffffffffffffff
  4. test is 3fffffffffffffff
  5. ...
  6. test is 1f
  7. test is f
  8. test is 7
  9. test is 3
  10. test is 1
  11. test is 64bit
说明32位ARM芯片上确实实现了64位数。
步骤二:添加测试代码

点击(此处)折叠或打开

  1. test = 3;
  2. printf("test0 is %llx\n",test);
  3. test += 1<<32;
  4. printf("test1 is %llx\n",test);
执行结果如下:
test is 64bit
test0 is 3
test1 is 3

问题出现了,test的值没叠加上去。
改为test += 0x100000000
执行结果如下:
test0 is 3
test1 is 100000003

结论,1<<32在32位的ARM芯片上是不是默认用一个32位寄存器左移,导致左移溢出,结果就是0?

再加个测试:

点击(此处)折叠或打开

  1. test = 3;
  2. printf("test0 is %llx\n",test);
  3. test += 0x100000000;
  4. printf("test1 is %llx\n",test);

  5. test = (test&0xffffffff00000000) + 8 ;
  6. printf("test2 is %llx\n",test);
  7. test = (test&0xffffffff) + 1;
  8. printf("test3 is %llx\n",test);
执行结果如下,完全符合预期:

所以问题解决,正确代码如下:

点击(此处)折叠或打开

  1. unsigned long long ullCurFrmPts=0;//app里用到的时间戳,微秒计
  2. unsigned int bf_stamp=0;
  3. unsigned int timestamp=0;//SDK提供的时间戳

  4. bf_stamp = ullCurFrmPts&0xffffffff);
  5. if(timestamp*1000 < bf_stamp) {
  6.     ullCurFrmPts = (ullCurFrmPts + 0x100000000);
  7. }
  8. ullCurFrmPts = (ullCurFrmPts&0xffffffff00000000)+timestamp*1000;

PS:近一年没写博客了,CU的排版还是这么垃圾,失望至极。
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(909) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值