3

gettimeofday取毫秒的溢出问题

 3 years ago
source link: https://wuzhiwei.net/one_overflow_issue/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

gettimeofday取毫秒的溢出问题

游戏最近上线,在de一系列bug。其中有个bug比较有意思,是碰撞攻击Boss时,第一下总是打了不算。因为攻击Boss加了50ms的无敌间隔,以防止Boss在短时间连续碰撞中被秒杀。

遂怀疑是取系统时间出了问题,但在Mac上调试,发现输出完全无误。直到连上了iPhone5进行真机调试时,发现获取系统时间的函数输出的是一个负数。

以下是取当前系统的毫秒数。

inline long getCurrentTime()
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;

出现此问题,显然是溢出了。由于tv.tv_sec的类型是long,而long在32位的机器上的范围为−2,147,483,648 -> 2,147,483,647

因为Mac运行的是64位的架构,而iPhone5是32位的架构,所以在Mac上没问题,而在iPhone5就出现问题了。

tv.tv_sec表示是Unix时间戳。写下本文时的unix时间戳为1425312506,乘1000后显然是溢出了。

解决方案很简单,用long long就行了。(读者注:在不支持long long类型的编译器上可以使用double类型。)

inline long long getCurrentTime()
    struct timeval tv;
    gettimeofday(&tv, NULL);
    long long ms = tv.tv_sec;
    return ms * 1000 + tv.tv_usec / 1000;

解决完这个bug,不禁想到当unix时间戳到了2,147,483,647会是怎么办。这个问题早就有人考虑到了,叫做2038年问题

也就是到了2038年1月19日3时14分07秒后,如果在32位设备上用long类型再表示unix时间戳就溢出了。。

image

第一行是“time_t”数字的二进制表示;第二行是其十进制表示;第三行是受影响的计算机理解的时间;第四行是实际的时间

不过到了2038年,还有32位设备么。。。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK