您的位置:首页 > 编程语言

如何编写可调试自诊断代码?

2007-07-30 22:16 218 查看
调试:用于程序开发时的系统行为修正,排除系统行为的缺陷,实现我们预期的功能
诊断:用于程序运行时的系统异常定位,判定系统对异常行为的响应,以便于采取措施实施治疗和规避 

通常情况下,我们会在程序中就异常、错误情况进行处理,我们将错误信息记入日志,以便于进行跟踪和
判别。

调试问题:

1 打印模块错误,拷贝粘贴的结果

  解决办法:不用手工输入
2 打印级别混乱 :
  程序异常和处理错误不分开
  解决办法:简化打印级别,分异常,错误,调试
3 打印缺失:很多地方只返回FALSE,但是无任何打印,有的不对返回值进行判断
  解决办法:增加
4 不规范,存在个性化的打印

跟踪问题:

1 冗余打印:

2 信息却失

3  错误分支缺失

解决?

1 跟踪宏
2 为工程定制诊断日志
3 区分错误日志和跟踪日志

从标准的c++assert宏ASSERT,trace宏,

致命错误日志,向日志进程发送异常日志,控制程序的各种版本,在发生异常时,不允许中止服务器进程,
传统宏的功能:仅限于输入参数的检测

可定制更多宏在程序开发的早期捕获更多的错误,称为自诊断功能

分清楚非预期的错误和预期的错误,
调试宏集:
容易使用的函数和宏,语义清晰
错误报告发送至文件或调试控制台
宏可以关闭和打开,不影响正常程序的运行
调试宏可以透明的集成到源代码,可以在发布版本中删除,不能对程序有任何影响
依赖于条件定义,错误报告可以被利用,不管是调试版本和发布版本

调试宏的条件:
宏应该尽可能的报告错误信息,位置,模块,错误码,错误信息,最近的系统错误
在没有错误时,宏必须尽量减轻系统的负担,但有错误必须汇报
调试宏不能依赖于rtti,,某些系统不可用
调试宏必须允许多线程,多进程并发的向错误日志报告,由于致命错误较少,同步机制尽可能简单
当错误发生时的应用或DLL的版本号,如果有多个DLL共享某些源码,可以定位源码的正确版本

断言的意图数验证设计决定,造成他失败的唯一原因应该是程序逻辑有缺陷。理想的结果是在开发阶段就就决调所有违背断言的情况。
如果某个条件不完全在程序的控制之下,那么不要对这个条件使用断言。不应该使用断言来验证函数的参数。

用错误处理代码来处理预期会发生的情况,用断言来处理绝不应该发生的状况
错误处理通常用来检查有害的输入数据,断言用于检查代码中的bug

举例:

 

#define no_value

#ifdef  hsdb_assert
#define assert_next(prnlevel,  expr)/
            ((expr)? ((void)0): _dbException_Mdl(dbPrnHlr,prnlevel,"Expression: ( "#expr" ) is false in file:%s,line :%d ",__FILE__, __LINE__))
#else
#define assert_next(prnlevel,  expr)   (expr)
#endif           

#ifdef  hsdb_assert
#define assert_para(prnlevel,  expr)/
            ((expr)? ((void)0): _dbException_Mdl(dbPrnHlr,prnlevel,"Expression: ( "#expr" ) is false in file:%s,line :%d ",__FILE__, __LINE__))
#else
#define assert_para(prnlevel,  expr)   (expr)
#endif

void assertion_failed (char const * expr, char const * file, long line)
{
      _dbException_Mdl(dbPrnHlr,mtPrnImp_M, ("Expression: %s is false in file: %s line: %d", expr, file, line);
}

#ifdef  hsdb_assert
#define assert_failed(expr) /
      if(!(expr))  assertion_failed(#expr,__FILE__, __LINE__)
#endif

#ifdef  hsdb_assert
#define assert_succeed(expr)  return (expr)
#endif

#ifdef  hsdb_assert
#define assert_return(prnlevel,  expr, return_value)/
            if(!(expr))/
            { /
                _dbException_Mdl(dbPrnHlr,prnlevel,"Expression: ( "#expr" ) is false in file:%s,line :%d ",__FILE__, __LINE__));/
                return (return_value);/
       }             
#endif

#ifdef  hsdb_assert
#define assert_return_ex(prnlevel,  expr, return_value,ack_return, ack_return_value)/
            if(!(expr))/
            { /
                _dbException_Mdl(dbPrnHlr,prnlevel,"Expression: ( "#expr" ) is false in file:%s,line :%d ",__FILE__, __LINE__));/
                ack_return = ack_return_value;/
    return (return_value);/
       }
#endif

typedef void (*checkFunc)(LPSTR,LPSTR);

typedef  tracepoint

    char szFunName[40]; /* 检查点所在的函数的名字 */
    unsigned int  uiLine; /* 检查点所在的行号 */
    checkFunc  tracecheck ;   
}trace_point;

typedef  traceSuit
{
    char  sztraceSuitName[40];
 unsigned int suitID;
    unsigned int uicheckPointount;/**/
    trace_point   tracepointlist[40];
}trace_suit;

typedef  tracesuitregistry
{
     unsigned int tracesuitcount;
      trace_suit  tracesuitlist[50];

}tracesuit_registry;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息