好久没写博客了,昨天遇到一个时间计数溢出问题, 做个简单记录吧
背景:底层提供一个unsigned int的变量表示自开机以来累计时间,用作码流的时间戳,单位ms.
问题:32位无符号数的毫秒计数,大概49天就会溢出,溢出后时间计数用作时间戳就会出错,导致无法正确解码。
为解决这一问题,用一个64位变量来保存累计时间,
方法如下:
-
unsigned long long ullCurFrmPts=0;//app里用到的时间戳,微秒计
-
unsigned int bf_stamp=0;
-
unsigned int timestamp=0;//SDK提供的时间戳
-
-
bf_stamp = ullCurFrmPts&0xffffffff);
-
if(timestamp*1000 < bf_stamp) {
-
ullCurFrmPts = (ullCurFrmPts + 1<<32);
-
}
-
-
ullCurFrmPts = (ullCurFrmPts&0xffffffff00000000)+timestamp*1000;
运行,时间怎么都不对
找问题步骤1:
先确定32位ARM上实现的unsigned long long是否64位?
测试代码
-
int num=0;
-
unsigned long long test=0;
-
-
test = ~0;
-
printf("test is %llx\n",test);
-
num=0;
-
while(1){
-
if(test&0x1){
-
num++;
-
}
-
test = test>>1;
-
if (test == 0)break;
-
printf("test is %llx\n",test);
-
}
-
printf("test is %dbit\n",num);
执行结果如下
-
[root@GM]# ./test
-
test is ffffffffffffffff
-
test is 7fffffffffffffff
-
test is 3fffffffffffffff
-
...
-
test is 1f
-
test is f
-
test is 7
-
test is 3
-
test is 1
-
test is 64bit
说明32位ARM芯片上确实实现了64位数。
步骤二:添加测试代码
-
test = 3;
-
printf("test0 is %llx\n",test);
-
test += 1<<32;
-
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?
再加个测试:
-
test = 3;
-
printf("test0 is %llx\n",test);
-
test += 0x100000000;
-
printf("test1 is %llx\n",test);
-
-
test = (test&0xffffffff00000000) + 8 ;
-
printf("test2 is %llx\n",test);
-
test = (test&0xffffffff) + 1;
-
printf("test3 is %llx\n",test);
执行结果如下,完全符合预期:
所以问题解决,正确代码如下:
-
unsigned long long ullCurFrmPts=0;//app里用到的时间戳,微秒计
-
unsigned int bf_stamp=0;
-
unsigned int timestamp=0;//SDK提供的时间戳
-
-
bf_stamp = ullCurFrmPts&0xffffffff);
-
if(timestamp*1000 < bf_stamp) {
-
ullCurFrmPts = (ullCurFrmPts + 0x100000000);
-
}
-
ullCurFrmPts = (ullCurFrmPts&0xffffffff00000000)+timestamp*1000;
PS:近一年没写博客了,CU的排版还是这么垃圾,失望至极。
阅读(3513) | 评论(0) | 转发(0) |