[转贴] 从零开始学C++之异常(二):程序错误、异常(语法、抛出、捕获、传播)、栈展开
一、程序错误
编译错误,即语法错误。程序就无法被生成运行代码。
运行时错误
不可预料的逻辑错误
可以预料的运行异常
例如:
动态分配空间时可能不会成功
打开文件可能会失败
除法运算时分母可能为0
整数相乘可能溢出
数组越界……
二、异常
(一)、异常语法
throw 表达式;
try
{
//try语句块
}
catch(类型1 参数1)
{
//针对类型1的异常处理
}
catch (类型2 参数2)
{
//针对类型2的异常处理
}
…
catch (类型n 参数n)
{
//针对类型n的异常处理
}
(二)、异常抛出
可以抛出内置类型异常也可以抛出自定义类型异常
throw抛出一个类对象会调用拷贝构造函数
异常发生之前创建的局部对象被销毁,这一过程称为栈展开
(三)、异常捕获
一个异常处理器一般只捕捉一种类型的异常
异常处理器的参数类型和抛出异常的类型相同
…表示可以捕获任何异常
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
#include <iostream>
#include <string> using namespace std; class MyException const char *what() const |
程序自定义一个异常类型MyException,从输出可以看出,Divide函数内先构造一个MyException对象e,调用构造函数,因为e是局部对象需要被析构,在析构前先调用拷贝构造函数构造另一个对象,这个对象将被catch 引用,最后这个对象在catch末尾也将被析构。
假设没有构造局部对象,直接throw , 如 throw MyException("division by zero"); 那么将不会调用拷贝构造函数,只存在一个对象,在catch的末尾被析构。
假设throw 1; 而没有对应的catch (int) ,即使存在catch (double) 也捕获不到,不会做类型转换,此时会由catch (...) 捕获到,...表示可以捕获任何异常。
(四)、异常传播
1、try块可以嵌套
2、程序按顺序寻找匹配的异常处理器,抛出的异常将被第一个类型符合的异常处理器捕获
如果内层try块后面没有找到合适的异常处理器,该异常向外传播,到外层try块后面的catch块中寻找
3、没有被捕获的异常将调用terminate函数,terminate函数默认调用abort终止程序的执行
可以使用set_terminate函数指定terminate函数在调用abort之前将调用的函数
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
void MyTerminate()
{ cout << "MyTerminate ..." << endl; } int main(void) |
其中MyException类如上,程序中将内层的catch (MyException& e) 屏蔽了,所以由外层的catch (MyException& e) 捕获,假设将两个都注释掉的话,因为没有找到合适的catch, 那么terminate 函数会被调用,并且由于事先set_terminate
函数设定了abort调用之前被调用的函数MyTerminate,故先输出MyTerminate ...然后程序被终止。
三、栈展开
沿着嵌套调用链接向上查找,直至为异常找到一个catch子句。这个过程称之为栈展开。
为局部对象调用析构函数
析构函数应该从不抛出异常
栈展开期间会执行析构函数,在执行析构函数的时候,已经引发的异常但还没处理,如果这个过程中析构函数又抛出新的异常,将会调用标准库的terminate函数。
异常与构造函数
构造函数中可以抛出异常。如果在构造函数函数中抛出异常,则可能该对象只是部分被构造。即使对象只是被部分构造,也要保证销毁已构造的成员。(如果成员是指针p,因为析构函数不会被调用,故不会执行一般的delete p; 很可能造成内存泄漏)
[转贴] 从零开始学C++之异常(二):程序错误、异常(语法、抛出、捕获、传播)、栈展开的更多相关文章
- Spring事务异常回滚,捕获异常不抛出就不会回滚(转载) 解决了我一年前的问题
最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了....... 为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常 ...
- cocos2d-x 错误异常抛出捕获和崩溃拦截
Error对象 一旦代码解析或运行时发生错误,JavaScript引擎就会自动产生并抛出一个Error对象的实例,然后整个程序就中断在发生错误的地方. Error对象的实例有三个最基本的属性: nam ...
- C# 中异常抛出捕获机制--throw / try,catch,finally
try { messagebox.show("true"); } catch { messagebox.show("false"); } finally { m ...
- 从零开始学Electron笔记(二)
在之前的文章我们简单介绍了一下Electron可以用WEB语言开发桌面级应用,接下来我们继续说一下Electron的菜单创建和事件绑定. 我们接上一章的代码继续编写,上一章代码 https://www ...
- 从零开始学ios开发(二):Hello World!来啦!
今天看了书的第二章,主要介绍了一下Xcode的使用方法和一些必要的说明,最后做了一个“Hello World!”的小程序,其实就是在屏幕上用一个Label显示“Hello World!”,一行代码都没 ...
- 从零开始学ios开发(二十):Application Settings and User Defaults(下)
在上一篇的学习中,我们知道了如何为一个App添加它的Settings设置项,在Settings设置项中我们可以添加哪些类型的控件,这些控件都是通过一个plist来进行管理的,我们只需对plist进行修 ...
- 从零开始学安全(四十二)●利用Wireshark分析ARP协议数据包
wireshark:是一个网络封包分析软件.网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料.Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换,是目前 ...
- 从零开始学Linux系统(二)之基本操作指令
ifconfigping ip地址帮助:ping -t ip地址ping -c 次数 ip地址ping -s 包的大小关机重启:shutdown -h now reboot清屏:clear == C ...
- 从零开始学ios开发(二):Hello World!
今天看了书的第二章,主要介绍了一下Xcode的使用方法和一些必要的说明,最后做了一个“Hello World!”的小程序,其实就是在屏幕上用一个Label显示“Hello World!”,一行代码都没 ...
- Spring事务异常回滚,捕获异常不抛出就不会回滚
最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了....... 为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常 ...
随机推荐
- JVM笔记4:Java内存分配策略
简单来说,对象内存分配主要是在堆中分配.但是分配的规则并不是固定的,取决于使用的收集器组合以及JVM内存相关参数的设定 以下介绍几条基本规则(使用的ParNew+Serial Old收集器组合): 一 ...
- Adapter 适配器模式
将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 目标接口(Target):客户所期待的接口.目标可以是具体的或抽象的类,也可 ...
- magento 产品列表排序、分页功能
我们以 catalog_category_layered 控制器为例说明 在catalog.xml 找到catalog_category_layered配置段 <catalog_category ...
- 编译inotify报错
错误如下: configure: error: no acceptable C compiler found in $PATH 这是因为没有找到编译器的原因造成的 解决方法: 安装gcc [root@ ...
- poj2299 二分思想
poj2299 http://poj.org/problem?id=2299题意: 一个含有n个数的数组, 每次只能交换相邻的两个数, 求最少操作多少次可以使该数组变成一个有序数组(从小到大). ...
- linux x64下编译libjpeg,libpng,zlib
libJpeg编译: 下载libjpeg源码:http://www.ijg.org/,下载jpegsrc.v9a.tar.gz 解压源码,命令:tar -zxvf jpegsrc.v9a,源码文件夹为 ...
- php session_id()函数介绍及代码实例
session_id()功能: 获取设置当前回话ID. 函数说明: string session_id ([ string $id ] ) 参数: 如果指定了参数$id,那么函数会替换当前的回话id. ...
- 04_过滤器Filter_02_Filter解决中文乱码问题
[过滤器解决中文乱码问题实例] [工程截图] [web.xml] <?xml version="1.0" encoding="UTF-8"?> &l ...
- [工具]toolbox_graph基本操作
toolbox_graph提供了对3D模型的一些操作.MATLAB代码源自:http://www.mathworks.com/matlabcentral/fileexchange/5355-toolb ...
- c++学习笔记2(c++简单程序)
c++的简单程序 练习一: #include <iostream>int main(){std::cout<<"你好c++\n";int x;std::ci ...