以C++语言标准委员会现主席Herb Sutter老兄以及他编写的Exceptional系列(已出版的包括:《Exceptional C++》、《More Exceptional C++》、以及《Exceptional C++ Style》)为甚。。
主动调试和契约编程相辅相成,共同保证软件开发的质量。契约编程相当于经济生活中签订的各种合同,而主动调试相当于某方不遵守合同时采取的法律惩罚措施。
各种开发语言和开发工具都提供这些调试语句,标准C++提供了assert函数,MFC提供了ASSERT调试宏帮助我们进行主动调试,在实际工作中,建议统一使用MFC的ASSERT调试宏。
参数检查
对于编写的函数,除了明确的指定契约外,在函数开始处应该对传入的参数进行检查,确保非法参数传入时立即报告错误信息。例如:
- BOOL GetPathItem ( int i , LPTSTR szItem , int iLen )
- {
- ASSERT ( i > 0 ) ;
- ASSERT ( NULL != szItem ) ;
- ASSERT ( ( iLen > 0 ) && ( iLen < MAX_PATH ) ) ;
- ASSERT ( FALSE == IsBadWriteStringPtr ( szItem , iLen ) ) ;
- }
这样的检查只能够排除指针为空的情况,但是如果指针指向的是非法地址,或者指针指向的对象并不是我们需要的类型,上面的例子就没有办法检查出来,而是统统认为是正确的。完整的检查应该如下:
- // An example of checking only a part of the error condition
- BOOL EnumerateListItems ( PFNELCALLBACK pfnCallback )
- {
- ASSERT ( NULL != pfnCallback ) ;
- }
恰当地在代码中使用ASSERT,对bug检测和提高调试效率有极大的帮助,下面举个简单的例子加以说明。
- switch( nType )
- {
- case GK_ENTITY_POINT:
- // do something
- break;
- case GK_ENTITY_PLINE:
- // do something
- break;
- default:
- ASSERT( 0 );
- }
在上面的例子中,switch语句仅仅处理了GK_ENTITY_POINT和GK_ENTITY_PLINE两种情况,应该是系统中当时只需要处理这两种情况,但是如果后期系统需要处理更多的情况,而此时上面这部分代码又没有及时更新,或者是因为开发人员一时疏忽遗漏了。
一个可能导致系统错误或者崩溃的bug就出现了,而使用ASSERT可以及时地提醒开发人员他的疏忽,尽可能快的消灭这个bug。还有一些情况,在开发人员编写代码时,如果能够确信在某一点出现情况A就是错误的,那么就可以在该处加上ASSERT,排除情况A。#t#
综上所述,恰当、灵活的使用ASSERT进行主动调试,能够极大提高程序的稳定性和安全性,减少调试时间,提高工作效率。综上所述,恰当、灵活的使用ASSERT进行主动调试,能够极大提高程序的稳定性和安全性,减少调试时间,提高工作效率。