C++程序设计ch13 程序设计的防错PPT演示课件_第1页
C++程序设计ch13 程序设计的防错PPT演示课件_第2页
C++程序设计ch13 程序设计的防错PPT演示课件_第3页
C++程序设计ch13 程序设计的防错PPT演示课件_第4页
C++程序设计ch13 程序设计的防错PPT演示课件_第5页
已阅读5页,还剩36页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

,面向对象程序设计与实践,第13章程序设计的防错,主讲人:杨峰,0,Page1,本课主要内容,保证程序的正确性异常函数的防错测试调试,1保证程序的正确性,1.1什么是程序的正确性?实现正确的软件正确的实现软件,Page2,1.2实现正确的软件,编写的软件应满足用户的要求至少应满足以下3个要求:对于所有正确的输入能产生正确的结果。对于所有不正确的输入能给出合理的提示信息。程序运行遇到错误后能终止程序的运行。较高要求包括:硬件故障情况下,程序能继续运行或合理终止(掉电、硬盘损坏,网络故障等)系统软件故障情况下,程序能继续运行或合理终止(操作系统,数据库管理系统等)对于商业和工业应用的实用化系统应能满足较高要求,比如电子商务系统,医疗系统,工业控制系统等。,Page3,1.3正确的实现软件,编写的程序应该尽量减少错误程序开发过程中会出现4种错误:编译错误(compile-timeerrors)。编译器发现的错误,说明程序代码不符合计算机语言规定的语法标准。链接错误(link-timeerrors)。链接器发现的错误,一般是函数实现与函数声明不对应,全局变量未定义,未链接需要的库等。运行时错误(run-timeerrors)。一般表示与硬件或系统软件发生冲突,比如网络中断,硬盘耗尽,硬件中断错误,软件中断错误,资源读写竞争,除0等等。逻辑错误(logicerrors)。程序编写中有bug,程序不能得到正确的计算结果。,Page4,1.4如何减少错误,一般原则通过良好的代码组织减少错误,减小错误的影响范围(充分利用函数和类实现封装,如果出现错误,尽量把错误的范围限制在封装的范围内,不波及到程序的其它部分)通过调试和测试消除错误。通过以上方法尽量减少错误,并使得未发现和未纠正的错误不会严重影响程序的正常运行。编写正确的程序虽然需要大量的实践经验,但是从一开始就进行良好的训练更重要。,Page5,2解决错误,解决编译错误编译错一般都是语法错误,比如:写掉了行尾的;号把英文的;号写成了汉字的;号括号没有配对类型名称,变量名称,函数名称,头文件名称键入错了等等。一般情况下,编译器给出的编译错误都是描述性的,根据其描述的内容查找到指定的代码行纠正语法错误就可以了。一般总是先解决第一个编译错指定的代码行,然后再编译。如果还有编译错,以此循环,直至消除全部编译错。,Page6,2解决错误,解决链接错误链接错误的原因很少,一般就3种情况:函数定义和函数声明不对应(一般是因为函数名键入错了)全局变量进行了声明和使用,但没有定义(前面加extern是全局变量的声明,而不是定义)没有链接需要的库(标准库是自动链接的,但其它的库,比如提供网络通信功能的库就需要告诉IDE库的名称和路径才能实现链接),Page7,2解决错误,解决运行时错误通过一套完整的错误检查,报告与处理机制来解决运行时错误解决逻辑错误通过调试和测试手段来解决逻辑错误,Page8,3函数的防错设计,函数设计的基本原则:函数负责检查和报告错误;函数的调用者负责处理错误报告错误的4种方式函数的返回值全局的错误变量;assert宏异常,Page9,3.1报告错误(Errorreport),通过返回值报告错误返回整型和指针类型的函数可以通过返回值报告错误整型返回值返回负数表示函数执行中出现了运行时错误,不能得到预期的结果。各种负返回值应该定义为符号常量或const常量。指针返回值返回空指针表示函数执行中遇到了错误或没有执行函数功能。,Page10,3.1报告错误(Errorreport),示例:,Page11,constintTheFirstError=-1;constintTheSecondError=-2;constintTheThirdError=-3;.intFunc(argumentlist).if(.)returnTheFirstError;.if(.)returnTheSecondError;.return0;,Page11,3.1报告错误(Errorreport),通过全局的错误变量浮点型的返回值任何一个浮点型的值都是合法的结果,找不到一个可以表示函数执行错误的值作为返回值。使用全局的errno变量报告函数执行出现运行时错误。全局变量errnoC标准库的头文件中声明了一个全局变量errno存储错误代码。一些库函数通过给errno赋值来产生函数执行出错的信号。在调用函数后,可以检查errno的值是否为0检查函数执行是否正常。在调用前需要将errno清0,因为这是一个全局变量,函数只管修改它的值,而不管复原它。,Page12,3.1报告错误(Errorreport),Page13,errno=0;y=sqrt(x);if(errno!=0)fprintf(stderr,sqrterror,programterminated.n);exit(-1);,也可以执行perror函数输出错误信息,该函数原型为voidperror(constchar*);该函数向标准错误流输出参数字符串一个分号一个空格最后是errno相关的错误信息errno=0;y=sqrt(x);if(errno!=0)perror(sqrterror);exit(-1);自定义的函数也可以使用这个全局变量并定义自己的错误码。,Page13,3.1报告错误(Errorreport),通过assert宏,Page14,assert宏声明在中(C+是)其原型为voidassert(intexpression);带一个参数,这个参数是一个正常情况一定为真的表达式。每次执行到这个函数,就检查参数表达式的值,如果该值为假(0),则向stderr输出一行错误信息,并调用abort函数终止程序执行。显示的错误信息包括参数表达式,源文件名和代码行号。如:char*p=newcharN+1;assert(p);该代码保证p不为空。,3.1报告错误(Errorreport),通过异常报告错误C+中,如果函数执行过程中发生错误,则在发生错误的地方抛出一个异常(throwexception),函数不再往下执行。函数的调用者通过try-catch块捕获可能发生的异常并进行相应处理。,Page15,Page16,tryvectorv;intx;while(cinx)v.push_back(x);for(inti=0;i=v.size();+i)coutvi=viendl;catch(constout_of_range,3.1报告错误(Errorreport),使用哪种方式报告错误一般的区分原则是:函数返回值表示函数执行过程中可以预见到的不正常情况,比如文件打不开,数据库连不上,给sqrt一个负数参数等等。errno只是函数返回值的替代方案(找不到一个合适的返回值表示错误)assert用于检查完全不应该发生的情况(比如给指针参数提供一个空指针)assert宏只用于调试版本,而在发行版本中不起作用assert宏实际上是用来防止程序中出现的bug。异常主要用于编程时无法预见的运行时错误。如网络连接中断,硬盘耗尽等。以上原则并不是强制性的,4种方法都可以用。一般C程序习惯用前3种C+程序习惯用后2种,并且以抛出异常为主要的错误报告方式,返回值只在函数正常执行完成时才有用。,Page17,3.2函数的前置条件与后置条件,每个函数总是包含输入,处理和输出3个部分。函数对输入参数的正确性要求称为函数的前置条件(pre-conditions)。函数成功执行后产生的结果称为后置条件(post-conditions)。函数的前置和后置条件都应该在函数首部的注释中写明。,Page18,3.2函数的前置条件与后置条件,前置条件前置条件反映函数的输入参数的要求。如果输入参数不满足要求,建议采用assert宏或抛出异常的方式报告错误。,Page19,用assert宏:voidmy_strcpy(char*dest,constchar*src)assert(dest,3.2函数的前置条件与后置条件,前置条件,Page20,用异常:doublearea(doublea,doubleb,doublec)if(ac,3.2函数的前置条件与后置条件,后置条件后置条件描述函数成功执行后的结果。如果函数只通过返回值返回,则应当描述这个返回值。如果函数还通过参数返回值,要描述对参数的修改内容。,Page21,如阶梯型电阻电路示例:voidgetResists(doublers,intrs_num)函数的后置条件就是接收用户输入,向电阻值数组中填充rs_num个电阻值,每个电阻值都大于0。又如冒泡排序示例:templatevoidBubbleSort(vector,Page23,4.1异常的作用,抛出异常的过程:构造一个异常类的变量,然后抛出。if(a0|b0|c0)throwinvalid_argument(边长不能为负);这是一个简写的形式,完整的代码可以如下:if(a0|b0|c0)invalid_argumenterror(边长不能为负);throwerror;invalid_argument是标准库定义的标准异常类,其构造函数带有一个参数,表示出错信息。,Page24,4.1异常的作用,抛出异常以后函数中,执行到抛出异常的语句就和执行到return语句一样,函数出栈,所有局部变量析构,如果函数中动态分配了内存或其它资源没有释放就会产生内存泄漏C+编程建议,类应该在构造函数中动态分配内存或资源,在析构函数中释放函数抛出异常出栈以后,与return不同,代码并不是回到调用函数的地方,而是跳转到捕获该异常的代码处,如果该异常没有被捕获,程序就会自动终止(异常终止),Page25,4.2标准异常,标准异常的基类是exception。该类含有一个成员函数what()用于提供出错信息,函数原型:virtualconstchar*what();,Page26,4.2标准异常,exception的派生类分为3类:语言核心的异常,直接派生自exception。包括bad_alloc,bad_cast,bad_typeid,bad_exception。这些异常由运行时抛出,用户程序不应抛出这些异常。逻辑异常,派生自logic_error。表示程序运行中出现了逻辑错误(表示程序有bug)。包括length_error(长度过长),domain_error(专业领域范围内的错误),out_of_range(下标访问越界),invalid_argument(无效参数)。还有一个ios_base:failure(直接派生自exception),表示I/O过程中出现了错误。运行异常,派生自runtime_error。表示运行中遇到了不可预知的运行错误。包括range_error(内部运算超出数据类型范围),overflow_error(算术运算上溢),underflow_error(算术运算下溢)。运行异常也由运行时抛出,用户程序不抛出这些异常。,Page27,4.3实现自己的异常,异常类都是很简单的类,构造函数接收一个描述错误的字符串。为和标准异常类行为一致,提供一个what()成员函数返回错误描述字符串。,classbaseExceptionpublic:baseException(conststring,Page28,4.3实现自己的异常,classmemoryAllocationError:publicbaseExceptionpublic:memoryAllocationError(conststring,然后再派生一些更特化的异常类。这些派生类不增加任何成员,只用于标识不同的运行错误。,Page29,4.4捕获异常,函数抛出异常,调用函数通过try-catch块捕获异常。调用可能发生异常函数的代码应包围在中try-catch块中。catch语句用于捕获异常,语法格式为:try可能抛出异常的代码catch(异常类型变量名)处理异常的代码,Page30,4.4捕获异常,catch接收一个异常类型变量作为参数,可以是普通类型,也可以是引用类型。为保证what()执行的多态效果,最好用引用类型。catch块的处理通常比较简单,打印异常变量提供的信息,然后返回或退出程序。一个try块可以后接多个catch块捕捉最特化的异常类放在最前面越泛化的异常类放在后面最后一个catch块用号表示捕捉所有未指定的异常。,Page31,4.4捕获异常,try.catch(constindexRangeError,4.4捕获异常,Page32,5测试和调试,5.1测试测试的概念测试简单的说就是通过一组选择的输入检查程序的输出是否是期望的结果要点:如何选择输入数据白盒测试黑盒测试掌握程序正确的输出结果,Page33,5.1测试,测试的组织单元测试就是测试每个单个的函数单元测试可以采用黑盒和白盒测试系统测试是将所有经过测试的函数组装在一起进行测试系统测试采用黑盒测试系统测试除了测试程序的逻辑错误外,也可以有意的测试系统对运行时错误的反应,比如拔掉网线,机器掉电,制造硬盘满现象,制造大量的并发访问流量等,Page34,5.1测试,以阶梯型电阻电路为例:目标:编写3个函数,输入阶梯型电阻电路的参数,输出电路的参数,计算电路的等值电阻。3个函数逐个实现和测试,都完成以后再组装进行系统测试。过程:首先实现和测试输出电路参数的函数(因为输出功能正确实现后,才能知道输入的值是否正确)先写一个假的输入函数,称为stub(占位函数)。这个函数可以简单的用一个循环给存放电阻值的向量中任意存入一些数字然后编写main函数调用这2个函数(此时main函数是一个测试驱动Driver)。测试用例可以选择向量中有0个数据,有少量数据,有很多数据3种情况进行测试。,Page35,Page35,5.1测试,以阶梯型电阻电路为例:过程:再实现和测试输入参数的函数。测试时可以故意输入阻值0,一个电阻值也不输入,输入奇数个电阻值,输入负数和输入正常的偶数个正数几种情况进行测试。最后实现和测试计算等值电阻的函数。输入一些特别设计的电阻值,这些电阻值使得等值电阻和端口电流很容易计算比对程序计算结果和应得结果。3个函数都完成以后,修改main函数为最终的实现。然

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论