前几天发生了一个BUG, 用掉了几个小时,记录下.
逻辑:
ProgA启动ProgB, ProgA主动退出.
ProgB被启动后, 如果发现ProgA没退出完成, 杀掉ProgA.
ProgB替换ProgA为新版程序, 启动ProgA, ProgB主动退出.
Bug:
在开发机上, ProgB每次都可以替换启动ProgA.
在同事的计算机上,ProgB大多数情况下,都不能替换启动ProgA. 频率很高.
分析:
替换不成功ProgA文件的原因是, ProgA当时还在运行,导致替换失败.
最后,怀疑到KillPid函数上, 为啥ProgB没杀掉.
最后,通过日志发现, ProgB KillPid杀掉的程序是ProgB自己.
做了个试验,可以证明,程序自己杀自己,是可以杀掉的.
当天晚上,一直再想这事.
在同事计算机上, Debug版也是能重现Bug的.
如果开发时,在killPid函数中,加入断言。当出现这个断言时,可以很清楚的知道,是KillPid的入参PID找的不对.
以前,在Debug中,对于空指针之类的入参可能性,都加了断言.
以后,在可能出现程序逻辑错误的地方, 也要加入断言, 修复Bug的时间,就会大幅度减少.
BOOL KillProcessByPid(long lPid)
{
BOOL bRc = FALSE;
DWORD dwRc = 0;
HANDLE hProcess = NULL;
/// 可以杀掉自己, 已经试验过, 直接跑程序, 自己可以杀掉自己
/// 这函数主要是来杀其它进程的
/// 自己要想退出, 按照正常流程退出即可. 如果出现杀自己的情况, 说明有逻辑错误.
_ASSERT(lPid != ::GetCurrentProcessId()); ///< !! 逻辑错误
if (lPid == ::GetCurrentProcessId())
return FALSE;
EnablePrivilege(TRUE); ///< my function
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, lPid);
if(NULL != hProcess)
{
bRc = ::TerminateProcess(hProcess, dwRc);
}
else
{
WriteLog(L"can't open process PID = %d\r\n", lPid);
}
return bRc;
}
ps :
在自己的开发环境所在的计算机调试,感觉很好。
在用户或同事的计算机上调试程序,各种不便。
e.g.
* 每运行一个调试的更新,一个回合所花的时间更长. 这时,迅速的定位问题,显得很关键.
* 我那个同事的vs2010居然都不能修改工程中的rc文件, 只能用我的开发机上编译出的程序.
* 同事不喜欢装不用的软件, 日志文件是Unicode的, 用NotePad打开后,看着巨不习惯.
* 眼看着时间一分一秒的过去, 同事要陪着自己调试, 心里很内疚. 如果只有用户那能出现,那就更操蛋了.
作为程序员,自己能看到,测试到的Bug, 早就自己低调的消掉.
被同事和用户指出的BUG, 绝对是自己不能发现的。