[经验总结]获取Windows程序出错原因的C++代码

43 篇文章 0 订阅
43 篇文章 0 订阅

     上周的工作需要在代码中读写INI文件,但写INI文件的程序总是过不去,后经同事提示是INI文件被设为只读。问其如何才能得知此错误,只见他打开一个小工具,输入从调试窗口得到的ErrorCode,点“确定”之后,小窗口上显示出错原因“文件访问出错”。这种方式实在是低效,我想在程序中自动做这些工作。于是上网搜得《win32 多线程程序设计》一书中的错误处理代码,对其稍作修改就能使用。对原书代码修改主要体现以下三个方面:
    
1 > 将字符串类型改为Unicode;
    
2 > 删去PrintError函数中exit( EXIT_FAILURE );
    
3 > 原书代码中MTVERIFY宏如下:    

         #define MTVERIFY(a) if  (!(a)) PrintError(#a, __FILE__ , __LINE__ ,GetLastError())
         将其修改为Unicode版本:
         #define MTVERIFY(a) if  (!(a)) PrintError(_T(#a), _T( __FILE__ ), __LINE__ , GetLastError())
    这个宏能很好的工作,但有一个局限,不能将BOOL参数a返回给调用者,这个也是宏定义本身的局限。当调用者需要对出错情况进行处理,需要编写这样的代码。
              BOOL  retval;
              MTVERIFY(retval = do_something)
;
              
if  (retval) {
                    
// 错误处理 ... ...
              }
    最近在学Perl,Perl程序员的核心价值观就是“懒惰 急躁 傲慢“,那么可以再改造MTVERIFY宏,以少写两行代码。首先添加一个内联函数:
     __inline BOOL Myverify(BOOL what,LPTSTR lpszFunc)
    {
    #ifdef _DEBUG
            
if  (!what)
                       PrintError(_T(
__FILE__ ), __LINE__ , lpszFunc,GetLastError());
    #endif
    
            
return  what;
    }

    然后重写MTVERIFY宏:
           #define MTVERIFY(a) Myverify(a,_T(#a))
    如此这般,上述错误处理代码可以写成:
        
if  (MTVERIFY(a)) {
                            
// 错误处理 ... ...
         }
    虽然这一番折腾只能省下两行代码,但考虑到MTVERIFY函数以后会经常用到,从长远来看,省下的代码是2*N行 ,总的生产力会得到提升。所以,写代码,就该让“懒惰 ”进行到底。                  


    


/*
 * MtVerify.h
 *
 * The function PrintError() is marked as __inline so that it can be
 * included from one or more C or C++ files without multiple definition
 * errors.
 * To use the PrintError() in an application, it should be taken out,
 * placed in its own source file, and the "__inline" declaration removed
 * so the function will be globally available.
 * [Modified by thinkhy 10/01/04] ...
 * [Modified by thinkhy 10/01/07] Added function Myverify.
  */
 
#pragma comment( lib, "USER32"  )
 
#define MTASSERT(a) _ASSERTE(a)
 
 
#ifdef _DEBUG
#define MTVERIFY(a) Myverify(a,_T(#a))
#else
#define MTVERIFY(f)          (( void )(f))
#endif
 
__inline
void  PrintError(LPTSTR filename, int  lineno, LPTSTR lpszFunc, DWORD errnum)
{
    LPTSTR lpBuffer;
    TCHAR errbuf[
256 ];
#ifdef _WINDOWS
    TCHAR modulename[MAX_PATH];
#else   // _WINDOWS
    DWORD numread;
#endif   // _WINDOWS
 
    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
            | FORMAT_MESSAGE_FROM_SYSTEM,
            
NULL ,
            errnum,
            LANG_NEUTRAL,
            (LPTSTR)&lpBuffer,
// 这个参数很变态! [Commented by thinkhy 10/01/04]
            
0 ,
            
NULL  );
 
    wsprintf(errbuf, _T(
"Failed at Line: %d  in File: /" %s /"/r/n Function: %s   /r/n Reason: %s  " ),
                         lineno, filename, lpszFunc, lpBuffer);
#ifndef _WINDOWS
    WriteFile(GetStdHandle(STD_ERROR_HANDLE), errbuf, strlen(errbuf), &numread, FALSE );
    Sleep(
3000 );
#else
    GetModuleFileName(
NULL , modulename, MAX_PATH);
    MessageBox(
NULL , errbuf, modulename, MB_ICONWARNING|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
#endif
    
// exit(EXIT_FAILURE);
        
return ;
}
 
 
__inline BOOL Myverify(BOOL what,LPTSTR lpszFunc)
{
#ifdef _DEBUG
        
if  (!what)
                   PrintError(_T(
__FILE__ ), __LINE__ , lpszFunc,GetLastError());
#endif
 
        
return  what;
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值