Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1669439
  • 博文数量: 174
  • 博客积分: 5493
  • 博客等级: 上校
  • 技术积分: 5802
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-05 15:13
个人简介

炼狱,是为追逐光芒

文章分类

全部博文(174)

文章存档

2017年(1)

2016年(3)

2015年(9)

2014年(5)

2013年(23)

2012年(56)

2011年(45)

2010年(32)

分类: LINUX

2014-12-31 17:45:52

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

背景:底层提供一个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的排版还是这么垃圾,失望至极。
阅读(3414) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~