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

unsigned int的变量表示自开机以来累计时间,用作码流的时间戳,单位ms.

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

64位变量来保存累计时间,

方法如下:

此处)折叠或打开

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

= ullCurFrmPts&0xffffffff);
if(timestamp*1000 < bf_stamp) {
= (ullCurFrmPts + 1<<32);
}

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


运行,时间怎么都不对

1:

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


此处)折叠或打开

int num=0;
=0;

test = ~0;
("test is %llx\n",test);
num=0;
while(1){
if(test&0x1){
++;
}
= test>>1;
if (test == 0)break;
("test is %llx\n",test);
}
("test is %dbit\n",num);

执行结果如下


此处)折叠或打开

[root@GM]# ./test
is ffffffffffffffff
is 7fffffffffffffff
is 3fffffffffffffff
...
is 1f
is f
is 7
is 3
is 1
is

说明32位ARM芯片上确实实现了64位数。


步骤二:添加测试代码


此处)折叠或打开

问题出现了,test的值没叠加上去。

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

test is 64bit

test0 is 3

test1 is 3


改为test += 0x100000000


执行结果如下:

test0 is 3

test1 is 100000003


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


再加个测试:

此处)折叠或打开



test = 3;
("test0 is %llx\n",test);
+= 0x100000000;
("test1 is %llx\n",test);

= (test&0xffffffff00000000) + 8 ;
("test2 is %llx\n",test);
= (test&0xffffffff) + 1;
("test3 is %llx\n",test);

执行结果如下,完全符合预期:

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

此处)折叠或打开

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

= ullCurFrmPts&0xffffffff);
if(timestamp*1000 < bf_stamp) {
= (ullCurFrmPts + 0x100000000);
}
ullCurFrmPts = (ullCurFrmPts&0xffffffff00000000)+timestamp*1000;

PS:近一年没写博客了,CU的排版还是这么垃圾,失望至极。