c++中的异常捕获
传统的C语言错误判断
1.assert断言, 缺点:直接终止程序
2.errno错误, 缺点:返回错误码, 要去找对应的错误码描述
多数是errno形式, 严重错误会进行断言
c++异常概念:
try catch
捕获异常
throw
关键字, 抛出任何类型的异常
现有下面的函数:
显示结果:
这个异常可以在任何时候进行捕获:
比如, 中转函数调用也能捕获:
异常导致的安全问题
抛异常之后, 此异常代码之后的语句不会执行, 但是他也不会终止, 而是继续完成其他函数或者是类对象的析构,且在析构这些完成之后才显示出异常信息,这边就因为异常导致了执行流的跳跃,假设跳过的内容刚好是new之后对内存的delete,就会导致异常安全问题,看下文
异常信息与catch
类型不匹配也会捕获失败
当使用string抛异常时, 返回的是他的拷贝
实际抛出s的拷贝, 这边生成的拷贝在内部会调用移动拷贝
有时, 抛出的异常可能未在我们的预料之内, 所以使用catch ( . . . )捕获未知异常
在继承多态中:
当抛出派生类对象, 只需要捕获这个父类即可
在实际工程中, 错误的描述包含最重要的两个信息, 错误码和错误描述, 以及SQL相关的内容(对应异常的各类信息)也会进行记录
比如,在一个完整的服务体系中:
exception(异常) — 父类
sqlexception(sql异常) — 继承exception父类
cacheexception(缓存异常) — 继承exception父类
…
每个类中都对what()
什么异常的这个方法进行重写
在main函数中, 产生抛出异常的方式被父类捕获, 然后父类调用该子类对象的方法, 对应的错误描述对应的信息
异常体系
c++标准的异常体系
一般将父类的析构函数写成是多态, 指向父类调父类, 指向子类调用子类
异常安全
这边因为Division函数异常, delete没有被执行,导致内存泄露
解决方式1:
在所有写new delete的地方进行 try catch
解决方式2:(方便)
这只是一种array的new, 但当有多个array被new时, 这个错误就会形成嵌套的try catch, 这个问题下节智能指针来解决
c++98异常规范:
一般来说可以不写, 但是也没有限制, 希望写 可能的异常
明确知道这个异常不存在, 但是写上去也没有错, 因为编译器也不确定在将来的调用中, 会不会有这个异常发生
在异常时, throw()表示无异常, 但是实际这个函数有异常, 可以看到这个规则如同形同虚设, 但是建议写一下正确的异常, 而不是像下面这样:
总结:
在c++11中, 当你确定没有异常时, 加noexcep
关键字,
但是在明确有异常的函数加noexcept会将抛异常的机制进行忽略, 跟没加try catch一样,即使加try catch也会忽略
在右有异常时, 也就不要管,写好自己的try catch就好了, 不用像c++98那样,当然也兼容那种写法, 只是不推荐
异常的优缺点:
优点: 更清晰的展示错误的信息
在函数调用链很长的函数栈帧中, 可以直接跳到处理错误的地方
第三方库, boost gtest, gmock的使用, 也需要使用异常
部分异常的处理方式不方便使用返回值的形式,如 operator[](size_t pos)
缺点:
执行流乱跳
性能开销,现代硬件下可以忽略不计
易导致内存泄漏, 死锁问题
标准异常体系十分不好, 非常混乱
异常规范尽量使用, 都则后果不堪设想
ps: 当未知异常发生, 就会调用这个函数
喜欢不防来个三连支持一下~~~