如何编写可调试自诊断代码?
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;
诊断:用于程序运行时的系统异常定位,判定系统对异常行为的响应,以便于采取措施实施治疗和规避
通常情况下,我们会在程序中就异常、错误情况进行处理,我们将错误信息记入日志,以便于进行跟踪和
判别。
调试问题:
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;
相关文章推荐
- linux下调试程序和如何图形化调试,图形化工程代码编写与编译
- 如何使用Vim编写和调试Python代码
- 真正的C与C++编程高手是什么?臭美的群体!如何编写高质量代码?
- 简单学习如何在mac终端上编写c语言代码并编译
- 网页共用头部或共用底部该如何编写代码?
- Java在编写文件下载的代码中如何避免文件名乱码情况
- 如何在PB中编写PING代码
- 如何编写高质量的VB6代码
- 如何编写高质量和可维护的代码
- 老码农冒死揭开行业黑幕:如何编写无法维护的代码[ZZ]
- 如何编写优雅(地道)的Python代码 - 第三部分
- 如何编写远程登陆MOSS的代码
- 如何用 Visual studio 2003/2005 调试 ASP 应用程序、Javascript 代码
- 2017/12/23Java基础学习——如何通过记事本编写代码,并通过dos界面运行Java源文件
- 在使用Reference Source调试.Net 源代码时如何取消optimizations(代码优化)-翻译
- 如何在 Visual Studio 2013 中调试.NET Framework 4.5.1 代码
- 如何用Java编写一段代码引发内存泄露
- Linux下如何使用qt和anjuta来单步调试caffe的代码
- 如何在CHROME里调试前端代码?
- [转载]如何编写无法维护的代码(2)