c++ 异常与调试

常用异常处理

[参考] https://www.cnblogs.com/ranjiewen/p/5549929.html

1. assert 函数

  • 头文件:#include <assert.h>
  • 可以在头文件前加预定义宏关闭:#define NDEBUG 1
  • assert 只在debug编译中有效,例如cmake -D CMAKE_BUILD\_TYPE=release .. assert无效
  • assert(expr); // 如果 expr 值为false,调用abort() 结束程序

2. exit 函数

  • exit(0); // 正常退出
  • exit(i); // i>0 则是异常退出
  • exit() 参数返回给系统

3. try{…} catch(expression e){…}

  • 可以try一个函数体:
    void fun() try{ ... } catch(...) {...}
  • 捕获所有标准异常用catch(...)
  • 标准异常:
异常描述
std::exception该异常是所有标准 C++ 异常的父类
std::bad_alloc该异常可以通过 new 抛出。
std::bad_cast该异常可以通过 dynamic_cast 抛出。
std::bad_exception这在处理 C++ 程序中无法预期的异常时非常有用。
std::bad_typeid该异常可以通过 typeid 抛出。
std::logic_error理论上可以通过读取代码来检测到的异常。
std::domain_error当使用了一个无效的数学域时,会抛出该异常。
std::invalid_argument当使用了无效的参数时,会抛出该异常。
std::length_error当创建了太长的 std::string 时,会抛出该异常。
std::out_of_range该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator
std::runtime_error理论上不可以通过读取代码来检测到的异常。
std::overflow_error当发生数学上溢时,会抛出该异常。
std::range_error 当尝试存储超出范围的值时,会抛出该异常。
std::underflow_error 当发生数学下溢时,会抛出该异常。

[参考] http://blog.51cto.com/lihaichuan/1198702

4. terminate 和 set_terminate 函数

  • try catch 只能捕获标准异常,当try中出现标准异常匹配不到的异常时,会调用系统的库函数terminate()(在头文件中),默认情况下,terminate()函数调用标准C库函数abort()使程序终止而退出。当调用abort函数时,程序不会调用正常的终止函数,也就是说,全局对象和静态对象的析构函数不会执行。
  • 通过使用标准的set_terminate()函数,可以设置自己的terminate()函数。自定义的terminate()函数不能有参数,而且返回值类型为void。另外,terminate函数不能返回也不能抛出异常,它必须终止程序。如果terminate函数被调用,这就意味着问题已经无法解决了
  • 例如std::vector.at()访问越界,会抛出一个std::out_of\_range ,而用[ ]访问try catch无法捕获这个异常
#include <iostream>
#include <vector>
#include <exception>
using namespace std;
int main() {
    vector<int> v = {1,2,3};
    try{
        cout << "v[3]=" << v.at(3) << endl;
    } catch (std::range_error e) {
        cout << e.what() << endl;
    }
}

运行结果:

terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 3) >= this->size() (which is 3)

使用 set_terminate()

#include <iostream>
#include <vector>
#include <exception>
using namespace std;

void terminate_usr() {
    cout << "terminate_usr(): unknown error! " << endl;
    exit(1);
}

int main() {
    set_terminate(terminate_usr);
    vector<int> v = {1,2,3};
    try{
        cout << "v[3]=" << v.at(3) << endl;
    } catch (...) {
        cout << " error " << endl;
    }
}

5. 调试常用宏

含义
FILE当前源文件名,char字符,使用/FC选项产生全路径
LINE当前源文件的行号,正数
DATE当前编译日期,char字符串,格式:Aug 28 2011
TIME当前编译时间,char字符串,格式:10:32:12
FUNC当前函数
FUNCTION当前函数
TIMESTAMP最后一次修改当前文件的时间戳,char字符串,格式:Sun Aug 28 13:05:34 2014
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值