先说下时间规律:49.71天;
这是一个很魔性的时间,因为GetTickCount函数,返回值是DWORD类型,单位毫秒,也就是unsigned int,最大值UINT_MAX,也就是4294967295,可以自己换算下天数:
UINT_MAX / 1000 / 24 / 3600 = 49.71
再看下示例代码:
DWORD g_dwLastTime = GetTickCount() //假设全局变量
void OnTimer()
{
DWORD dwCurTime = GetTickCount()
if(g_dwLastTime + 30*1000 < dwCurTime)
{
//to do
//此处问题出在:
//假设 g_dwLastTime 和 dwCurTime 基本相等,
//g_dwLastTime 如果已经接近 UINT_MAX 时,
//g_dwLastTime + 30*1000 可能已经超过 UINT_MAX,
//此事 g_dwLastTime + 30*1000 的结果可能介于 0 ~ 30*1000 之间,
//而dwCurTime依然是接近 UINT_MAX 的值,
//造成30*1000毫秒内,if条件恒成立
//要解决这个问题,也很简单,
//一种是用减法:dwCurTime - g_dwLastTime > 300*1000
//另一种是换个接口,使用 GetTickCount64() ,
//返回值是 LONGLONG类型的,
//估计程序员在有生之年,
//LONGLONG 就不会再碰上 49.71 这个魔性的轮回数值
}
}
故事简述:
公司平台的用户接入服务器,有个定时器,会判断玩家如果符合某个条件,并且超过30分钟没有任何操作,就会强制把玩家踢下线,而突然有一天,全平台用户都在掉线,然后过一段时间,又恢复正常了;
当时,找不出问题啊,一遍又一遍看代码,一遍又一遍反复测试,希望能重现,但就是无法复现,无法找出问题;
然后,无法排查的bug偶尔也会被搁置,渐渐的,都忘记全平台玩家掉线的问题。。。
突然有一天,又出现了,还是没找到。。。
有一天,又出现。。。
好几年之后,回顾代码时,突然想起来 49.71 这个魔性数字,
问题就此解决!!!