VC程序调试和纠错技巧总结
Author:LengF Time:2011-08-18
学习VC的win32编程有一段时间了,一直没时间总结这些比较好的方法给和我一样的新手编程爱好者。在此特别感谢朋友ancker的帮助和指导。本文涉及的一些技巧可能都是一些比较简单的思路。调试技巧只针对那些可以正常编译通过无法运行或者运行出错的情况。
1.输出法
我们在程序编写的时候需要注意将一些可能导致错误的地方,比如函数的返回值等等,因为有些函数如果返回错误那么他有可能影响下面的所有结果。举个例子:
hStatus=RegisterServiceCtrlHandler(SRV_NAME,(LPHANDLER_FUNCTION)ServiceHandler);
if (hStatus==0) return;
// 错误处理
status=GetLastError();
if(NO_ERROR!=status)
{
// 注册失败则停止服务
ServiceStatus.dwCurrentState=SERVICE_STOPPED;
ServiceStatus.dwCheckPoint=0;
ServiceStatus.dwWaitHint=0;
ServiceStatus.dwWin32ExitCode=0;
ServiceStatus.dwServiceSpecificExitCode=SpecilError;
SetServiceStatus(hStatus,&ServiceStatus);
return;
}
如果你没有看出上面这段小程序的问题在哪里那么推荐你继续往下看。首先简单说下RegisterServiceCtrlHandler是这册服务程序的控制处理函数,它的返回值类型是SERVICE_STATUS_HANDLE,即一个服务状态句柄。如果成功返回一个状态句柄,如果失败返回0,那么你再看这个程序貌似没错,错就错在下面的错误处理了。如果失败了返回是0,你就无法通过GetlastError执行了,那么就无法停止服务了。貌似这样处理也不会有什么问题是吧。但是我发现这段程序会导致你即使成功安装了服务也无法启动服务。
回到主题上来,输出法就是利用printf或者AfxMessageBox等输出错误的方法。当你无法确定错误位置的时候,就需要对每个可能出错的地方添加该输出语句,多看看GetLastError返回值。
同时由于服务程序的特殊性比较难以调试,分享两个小经验:
[1]通过在服务主函数,常定义为ServiceMain开始添加如下代码:
freopen("c:\\error.txt", "w+", stdout);
利用这个将标准的输出都写入到文本,但是添加这个还不够,需要你你认为可能错误的地方用函数printf,_tprintf等函数输出。
[2]服务程序的代码如果确认没有错误,那么我们一般将服务所要执行的功能放在一个线程中处理,那么如果没有服务是不是一样可以执行?没错,我们一般的main函数启动服务会常见到这个函数:
// 启动服务的控制分派机线程
StartServiceCtrlDispatcher(ServiceTable);
为了方便调试我们这样修改:
// 启动服务的控制分派机线程
if(StartServiceCtrlDispatcher(ServiceTable)==0)
{
WorkThread(NULL); // 直接启动工作线程
}
当我们写好的服务程序通过vc6.0直接运行的时候StartServiceCtrlDispatcher函数返回结果为0,那么就可以直接调试我们的工作线程代码了,一般我们的错误也都是这边问题。这样就不用一直在停止和启动服务徘徊了。
2.断点调试法
这个方法应该来说比较常见,一般针对于程序结果执行错误的情况。通常我们对于结果判断错误或者在程序中一些非意图上的结果执行得到错误结果,我们会在程序多个位置下断点,通过F5快捷键进行单步调试。查看变量的值来跟踪错误。
总结:
简单记下这两点,方便以后学习,积累和应用。
补充:软件开发 , Vc ,