一 如何合适处理程序的异常

news/2024/7/6 0:28:57


关于函数可能抛出的异常的一些声明
void f() throw() 表示f不允许抛出任何异常,即f是异常安全的。
void f() throw(...) 表示f可以抛出任何形式的异常。
void f() throw(exceptionType); 表示f只能抛出exceptionType类型的异常。


声明一个不抛出异常的函数后,你有责任保证在你的函数的实现里面不会抛出异常。


附上别人的一些心得,有空可以验证一下:
1) 函数后面声明 throw() 只是接口的提供者和接口的使用者间的默契或称协议。
2) 这种协议不影响正常的异常处理流程。
3) vc2005 会在编译器对这种协议的遵守情况进行检查,并在为遵守协议的情况下 给出警告。




用于打印调用堆栈的辅助函数,可以在异常发生的时候打印事故现场 :(需要编译时加上-g -rdynamic两个选项)
std::string getStacktrace()
{
    int size = 16;
    void * array[16];
    int stack_num = backtrace(array, size);
    char ** stacktrace = backtrace_symbols(array, stack_num);
    for (int i = 0; i < stack_num; ++i)
    {
        printf("%s\n", stacktrace[i]);
    }
    free(stacktrace);
}




创建自己的异常类,用于存储额外的异常信息:错误码,堆栈,错误信息等
class BaseException:public std::runtime_error
{
public:
    BaseException(int  errorCode, const std::string& errorMessage = "",const std::string &btInfo = "");
    ~BaseException() throw();
 
    int  getErrorCode(void) const;//异常错误码
 
    const char* what() const throw();//异常描述


    const char *getBtInfo() const throw();//异常发生时的堆栈




  private:
int errorCode;
std::string m_errorMsg;
std::string m_btInfo;
};




BaseException::BaseException(int errorCode, const std::string& errorMessage,,const std::string &btInfo) :
        std::runtime_error(errorMessage)
{
    m_errorCode = errorCode;
    m_errorMsg = errorMessage;
    m_btInfo = btInfo;
}






BaseException::~BaseException() throw()
{
    
}


int BaseException::getErrorCode(void) const
{
    return m_errorCode;
}


const char* BaseException::what() const throw()
{
  return m_errorMsg.c_str();
}




const char* BaseException::getBtInfo() const throw()
{
  return m_errorMsg.c_str();
}






1在程序的最外围,应该用try/catch将程序入口包起来,防止因为有异常没捕捉导致程序core


int main()
{
try
{
...//你的代码
}
catch(BaseException &base_exception)
{
//可以将异常信息写入到日志,以供后面追踪
Log.write(base_exception.getErrorCode(),base_exception.what(),base_exception.getBtInfo());
}
catch(BaseException &std_exception)
{
//可以将异常信息写入到日志,以供后面追踪
Log.write(std_exception.what());
}
catch(...)
{
//可以将异常信息写入到日志,以供后面追踪
Log.write("unknown error");
}


}




 2 正确处理new的问题,不应该直接使用系统的new,因为系统级的new有可能会抛出bad_alloc &memExp这种类型的异常,比较合适的做法应该是用创建工厂,例如:


int * createInt()
{
    int * tmp = null;
   try
    {
tmp = new int;
    }


   catch(bad_alloc &memExp)
   {
    //这里可以将异常信息捕获,然后抛出去,也可以将错误信息和堆栈信息一起抛出去,这样,在外围捕捉到异常时,可以比较容易确定异常发生的位置
         BaseException bad_exception(0,memExp.what(),getStacktrace());
throw bad_exception;
   }
}


3 通过new创建的对象,应该用std::shared_ptr之类的只能包装起来,比较安全


4 底层的数据接口,一定要搞明白会不会抛异常,如果会,就需要跟new一样包装一下,不然一旦出错,没有错误信息和堆栈信息,你都不知道发生什么事,比如C++11中的std::stoi,std::stod
就是会抛异常,需要包装一下


5 多线程程序,子线程的异常是不会被主线程的try/catch捕获的,因此每个子线程需要自己捕捉自己线程内部可能发生的异常






6  现在来考虑这样一个构造函数:


Type() : m_a(new TypeA), m_b(new TypeB){}


  假设成员变量m_a和m_b是原始的指针类型,并且和Type内的申明顺序一致。这样的代码是不安全的,它存在资源泄漏问题,构造函数的失败回滚机制无法应对这样的问题。如果new TypeB抛出异常,new TypeA返回的资源是得不到释放机会的. 
解决方法:
shared_ptr<TypeA> m_a; shared_ptr<TypeB> m_b;这样,我们就可以轻而易举地写出异常安全的代码:


Type() : m_a(new TypeA), m_b(new TypeB){}

}



7 处理进程可能会收到的信号:


进程可能会收到系统发送的信号,如果不处理某些信号,进程的默认响应是终止,因此,为保证正确性,应该正确的处理信号。



http://www.niftyadmin.cn/n/3927156.html

相关文章

记一次 .NET 某云采购平台API 挂死分析

一&#xff1a;背景 1. 讲故事 大概有两个月没写博客了&#xff0c;关注我的朋友应该知道我最近都把精力花在了星球&#xff0c;这两个月时间也陆陆续续的有朋友求助如何分析dump&#xff0c;有些朋友太客气了&#xff0c;给了大大的红包&#xff0c;哈哈&#x1f605;&#…

python sort函数返回值_Python专栏1

本专栏是杨伟超对Python软件的系列介绍1 Python简介根据官网宣传&#xff1a;Python[1]是一种面向对象的解释性高级编程语言&#xff0c;具有动态语义。在不同的教材里面&#xff0c;有不同的关于python的定义。但共通的一点是&#xff1a;Python是一门简洁且功能强大的语言。比…

Google C++开源项目风格指南

http://zh-google-styleguide.readthedocs.org/en/latest/google-cpp-styleguide/others/

std::bind的一个例子

用eclipse编译的话&#xff0c;要右键->property->c/Cbuild->Setting,把Cross GCC Compiler以及其他几个编译器的Miscellaneous中的Other flags 加上 -stdc11选项&#xff0c;才能编译通过// // Name : test.cpp // Author : tes // Version : // Cop…

记一次 .NET 某智慧水厂API 非托管内存泄漏分析

一&#xff1a;背景 1. 讲故事 七月底的时候有位朋友在wx上找到我&#xff0c;说他的程序内存占用8G&#xff0c;托管才占用1.5G&#xff0c;询问剩下的内存哪里去了&#xff1f;截图如下&#xff1a; 从求助内容看&#xff0c;这位朋友真的太客气了&#xff0c;动不动就谈钱…

记一次 .NET 某WMS仓储打单系统 内存暴涨分析

一&#xff1a;背景 1. 讲故事 七月中旬有一位朋友加wx求助&#xff0c;他的程序在生产上跑着跑着内存就飙起来了&#xff0c;貌似没有回头的趋势&#xff0c;询问如何解决&#xff0c;截图如下&#xff1a; 和这位朋友聊下来&#xff0c;感觉像是自己在小县城当了个小老板&a…

如何用eclipse开发有c++11新特性的C++程序

要右键->property->c/Cbuild->Setting,把Cross GCC Compiler以及其他几个编译器的Miscellaneous中的Other flags 加上 -stdc11选项&#xff0c;才能编译通过

关于std::string.length() std::string.size()

eclipse的代码提示获取到的描述&#xff1a;/// Returns the number of characters in the string, not including any /// null-termination. 意思大概是返回字符串的字符个数&#xff0c;不包括结束符 我的系统的ubuntu13.04,系统设置的编码如下&#xff1a; LANGzh_C…