异常处理
异常处理
主要内容 ·异常概述 ■C++的异常处理机制 ■程序调试
主要内容 ◼ 异常概述 ◼ C++的异常处理机制 ◼ 程序调试
异常概述 ■程序的错误通常包括: 语法错误:指程序的书写不符合语言的语法规 则。这类错误可由编译程序发现。例如: ■使用了未定义或未声明的标识符 ■左右括号不匹配 逻辑错误(或语义错误):指程序设计不当造 成程序没有完成预期的功能。这类错误可通过 对程序进行静态分析和动态测试发现。例如: ■把两个数相加写成了相乘 排序功能未能正确排序
异常概述 ◼ 程序的错误通常包括: • 语法错误:指程序的书写不符合语言的语法规 则。这类错误可由编译程序发现。例如: ◼ 使用了未定义或未声明的标识符 ◼ 左右括号不匹配 ◼ ...... • 逻辑错误(或语义错误):指程序设计不当造 成程序没有完成预期的功能。这类错误可通过 对程序进行静态分析和动态测试发现。例如: ◼ 把两个数相加写成了相乘 ◼ 排序功能未能正确排序 ◼
运行异常:指程序设计对程序运行环境考虑不 周而造成的程序运行错误。例如: ■对于“/y”操作,y输入了“零” ·由内存空间不足导致的访问空指针: int*p=new int;/动态分配空间,可能失败! *p三10;/如果上面new操作失败,p为空指针或抛出异常 ■输入数据的数量超过存放它们的数组的大小导致数组 下标越界。 多任务环境可能导致的文件操作错误。 ■给一个采用二分法查找的函数提供了一个未排序的数 组。 数据超出了其类型所允许的范围(溢出)
• 运行异常:指程序设计对程序运行环境考虑不 周而造成的程序运行错误。例如: ◼ 对于“x/y”操作,y输入了“零”。 ◼ 由内存空间不足导致的访问空指针: int *p=new int; //动态分配空间,可能失败! *p = 10; //如果上面new操作失败,p为空指针或抛出异常 ◼ 输入数据的数量超过存放它们的数组的大小导致数组 下标越界。 ◼ 多任务环境可能导致的文件操作错误。 ◼ 给一个采用二分法查找的函数提供了一个未排序的数 组。 ◼ 数据超出了其类型所允许的范围(溢出)。 ◼
逻辑错误与运行异常的比较 逻辑错误(环境正常,结果不正确 》 bool strlonger(char *str1,char *str2) return strlen(str1)-strlen(str2)>0; } strlonger("abc","1234")// 运行异常(环境正常,结果正确:环境不正常,结果不 正确) double sum(double a[],unsigned int len) double result=0.0; for (int i=0;i<=len-1;i++) result +a[i]; return result; sum(.,0)/?
◼ 逻辑错误(环境正常,结果不正确) bool strlonger(char *str1,char *str2) { return strlen(str1)-strlen(str2)>0; } • strlonger("abc","1234") //? ◼ 运行异常(环境正常,结果正确;环境不正常,结果不 正确) double sum(double a[], unsigned int len) { double result=0.0; for (int i=0; i<=len-1; i++) result += a[i]; return result; } • sum(...,0) //? 逻辑错误与运行异常的比较
在程序运行环境正常的情况下,导致运行异常的 错误是不会出现的 程序异常错误往往是由于程序设计者对程序运行 环境的一些特殊情况考虑不足所造成的。 导致程序运行异常的情况是可以预料的,但它是 无法避免的。 为了保证程序的鲁棒性(Robustness),必须 在程序中对可能的异常进行预见性处理
◼ 在程序运行环境正常的情况下,导致运行异常的 错误是不会出现的。 ◼ 程序异常错误往往是由于程序设计者对程序运行 环境的一些特殊情况考虑不足所造成的。 ◼ 导致程序运行异常的情况是可以预料的,但它是 无法避免的。 ◼ 为了保证程序的鲁棒性(Robustness),必须 在程序中对可能的异常进行预见性处理
■例如,下面程序的鲁棒性不高! void f(char *filename) ifstream file(filename); int X; file>>x;/如果filename指定的文件不 /存在,将会出现运行异常」 /异常时,的值不正确! ■■■■■■
◼ 例如,下面程序的鲁棒性不高! void f(char *filename) { ifstream file(filename); int x; file >> x; //如果filename指定的文件不 //存在,将会出现运行异常! ... x ... //异常时,x的值不正确! ...... }
处理异常的策略 就地处理 。 在发现错误的地方处理异常 ■异地处理 ·在其它地方(非异常发现地)处理异常
处理异常的策略 ◼ 就地处理 • 在发现错误的地方处理异常 ◼ 异地处理 • 在其它地方(非异常发现地)处理异常
异常的就地处理 常用做法是调用C++标准库中的函数exit 或aborts终止程序执行(在cstdlib或 stdlib.h中声明) ·abort立即终止程序的执行,不作任何的善后 处理工作 ext在终止程序的运行前,会做关闭被程序打 开的文件、调用全局对象和static存储类的局 部对象的析构函数(注意:不要在这些对象类 的析构函数中调用ext)等工作
异常的就地处理 ◼ 常用做法是调用C++标准库中的函数exit 或abort终止程序执行(在cstdlib或 stdlib.h中声明) • abort立即终止程序的执行,不作任何的善后 处理工作。 • exit在终止程序的运行前,会做关闭被程序打 开的文件、调用全局对象和static存储类的局 部对象的析构函数(注意:不要在这些对象类 的析构函数中调用exit)等工作
■例如: void f(char *filename) ifstream file(filename); if(file.fail(O)》 {coutX; } 不管abort:还是exit,都“not user-friendly
◼ 例如: void f(char *filename) { ifstream file(filename); if (file.fail()) { cout > x; ...... } ◼ 不管abort还是exit,都“not user-friendly