Linux 下 C++ 异常处理技巧

来源:互联网 发布:华微大数据营销平台 编辑:程序博客网 时间:2024/05/21 17:59

转载至:http://www.oschina.net/code/snippet_222150_18256

简介: 处理 C++ 中的异常会在语言级别上遇到少许隐含限制,但在某些情况下,您可以绕过它们。学习各种利用异常的方法,您就可以生产更可靠的应用程序。

保留异常来源信息

在 C++中,无论何时在处理程序内捕获一个异常,关于该异常来源的信息都是不为人知的。异常的具体来源可以提供许多更好地处理该异常的重要信息,或者提供一些可以附加到错误日志的信息,以便以后进行分析。

为了解决这一问题,可以在抛出异常语句期间,在异常对象的构造函数中生成一个堆栈跟踪。ExceptionTracer是示范这种行为的一个类。


清单 1. 在异常对象构造函数中生成一个堆栈跟踪 
 // Sample Program: // Compiler: gcc 3.2.3 20030502 // Linux: Red Hat #include <execinfo.h> #include <signal.h> #include <exception> #include <iostream> using namespace std; ///////////////////////////////////////////// class ExceptionTracer { public:     ExceptionTracer()     {         void * array[25];         int nSize = backtrace(array, 25);         char ** symbols = backtrace_symbols(array, nSize);         for (int i = 0; i < nSize; i++)         {             cout << symbols[i] << endl;         }         free(symbols);     } };

回页首

管理信号

每当进程执行一个令人讨厌的动作,以致于 Linux™ 内核发出一个信号时,该信号都必须被处理。信号处理程序通常会释放一些重要资源并终止应用程序。在这种情况下,堆栈上的所有对象实例都处于未破坏状态。另 一方面,如果这些信号被转换成 C++ 异常,那么您可以优雅地调用其构造函数,并安排多层 catch 块,以便更好地处理这些信号。

清单 2 中定义的SignalExceptionClass,提供了表示内核可能发出信号的 C++ 异常的抽象。SignalTranslator是一个基于SignalExceptionClass的模板类,它通常用来实现到 C++ 异常的转换。在任何瞬间,只能有一个信号处理程序处理一个活动进程的一个信号。因此,SignalTranslator采用了 singleton 设计模式。整体概念通过用于 SIGSEGV 的SegmentationFault类和用于 SIGFPE 的FloatingPointException类得到了展示。


清单 2. 将信号转换成异常 
 template <class SignalExceptionClass> class SignalTranslator { private:     class SingleTonTranslator     {     public:         SingleTonTranslator()         {             signal(SignalExceptionClass::GetSignalNumber(), SignalHandler);         }         static void SignalHandler(int)         {             throw SignalExceptionClass();         }     }; public:     SignalTranslator()     {         static SingleTonTranslator s_objTranslator;     } }; // An example for SIGSEGV class SegmentationFault : public ExceptionTracer, public exception { public:     static int GetSignalNumber() {return SIGSEGV;} }; SignalTranslator<SegmentationFault> g_objSegmentationFaultTranslator; // An example for SIGFPE class FloatingPointException : public ExceptionTracer, public exception { public:     static int GetSignalNumber() {return SIGFPE;} }; SignalTranslator<FloatingPointException> g_objFloatingPointExceptionTranslator;

回页首

管理构造函数和析构函数中的异常

在全局(静态全局)变量的构造和析构期间,每个 ANSI C++ 都捕获到异常是不可能的。因此,ANSI C++ 不建议在那些其实例可能被定义为全局实例(静态全局实例)的类的构造函数和析构函数中抛出异常。换一种说法就是永远都不要为那些其构造函数和析构函数可能 抛出异常的类定义全局(静态全局)实例。不过,如果假定有一个特定编译器和一个特定系统,那么可能可以这样做,幸运的是,对于 Linux 上的 GCC,恰好是这种情况。

使用ExceptionHandler类可以展示这一点,该类也采用了 singleton 设计模式。其构造函数注册了一个未捕获的处理程序。因为每次只能有一个未捕获的处理程序处理一个活动进程,构造函数应该只被调用一次,因此要采用 singleton 模式。应该在定义有问题的实际全局(静态全局)变量之前定义ExceptionHandler的全局(静态全局)实例。


清单 3. 处理构造函数中的异常 
 class ExceptionHandler { private:     class SingleTonHandler     {     public:         SingleTonHandler()         {             set_terminate(Handler);         }         static void Handler()         {             // Exception from construction/destruction of global variables             try             {                 // re-throw                 throw;             }             catch (SegmentationFault &)             {                 cout << "SegmentationFault" << endl;             }             catch (FloatingPointException &)             {                 cout << "FloatingPointException" << endl;             }             catch (...)             {                 cout << "Unknown Exception" << endl;             }             //if this is a thread performing some core activity             abort();             // else if this is a thread used to service requests             // pthread_exit();         }     }; public:     ExceptionHandler()     {         static SingleTonHandler s_objHandler;     } }; ////////////////////////////////////////////////////////////////////////// class A { public:     A()     {         //int i = 0, j = 1/i;         *(int *)0 = 0;     } }; // Before defining any global variable, we define a dummy instance // of ExceptionHandler object to make sure that // ExceptionHandler::SingleTonHandler::SingleTonHandler() is invoked ExceptionHandler g_objExceptionHandler; A g_a; ////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) {     return 0; }

回页首

处理多线程程序中的异常

有时一些异常没有被捕获,这将造成进程异常中止。不过很多时候,进程包含多个线程,其中少数线程执行核心应用程序逻辑,同时,其余线程为外部 请求提供服务。如果服务线程因编程错误而没有处理某个异常,则会造成整个应用程序崩溃。这一点可能是不受人们欢迎的,因为它会通过向应用程序传送不合法的 请求而助长拒绝服务攻击。为了避免这一点,未捕获处理程序可以决定是请求异常中止调用,还是请求线程退出调用。清单 3 中ExceptionHandler::SingleTonHandler::Handler()函数的末尾处展示了该处理程序。

我简单地讨论了少许 C++ 编程设计模式,以便更好地执行以下任务:

  • 在抛出异常的时候追踪异常的来源。
  • 将信号从内核程序转换成 C++ 异常。
  • 捕获构造和/或析构全局变量期间抛出的异常。
  • 多线程进程中的异常处理。

我希望您能采用这些技巧中的一些来开发无忧代码。

标签: <无>

代码片段(3)

1. [代码]1. 在异常对象构造函数中生成一个堆栈跟踪     

?
 
// Sample Program:
// Compiler: gcc 3.2.3 20030502
// Linux: Red Hat
#include <execinfo.h>
#include <signal.h>
#include <exception>
#include <iostream>
usingnamespace std;
/////////////////////////////////////////////
classExceptionTracer
{
public:
    ExceptionTracer()
    {
        void* array[25];
        intnSize = backtrace(array, 25);
        char** symbols = backtrace_symbols(array, nSize);
        for(inti = 0; i < nSize; i++)
        {
            cout << symbols[i] << endl;
        }
        free(symbols);
    }
};

2. [代码]2. 将信号转换成异常     

?

template<classSignalExceptionClass> classSignalTranslator
{
private:
    classSingleTonTranslator
    {
    public:
        SingleTonTranslator()
        {
            signal(SignalExceptionClass::GetSignalNumber(), SignalHandler);
        }
        staticvoid SignalHandler(int)
        {
            throwSignalExceptionClass();
        }
    };
public:
    SignalTranslator()
    {
        staticSingleTonTranslator s_objTranslator;
    }
};
// An example for SIGSEGV
classSegmentationFault : publicExceptionTracer, publicexception
{
public:
    staticint GetSignalNumber() {returnSIGSEGV;}
};
SignalTranslator<SegmentationFault> g_objSegmentationFaultTranslator;
// An example for SIGFPE
classFloatingPointException : publicExceptionTracer, publicexception
{
public:
    staticint GetSignalNumber() {returnSIGFPE;}
};
SignalTranslator<FloatingPointException> g_objFloatingPointExceptionTranslator;

3. [代码]3. 处理构造函数中的异常

?
classExceptionHandler
{
private:
    classSingleTonHandler
    {
    public:
        SingleTonHandler()
        {
            set_terminate(Handler);
        }
        staticvoid Handler()
        {
            // Exception from construction/destruction of global variables
            try
            {
                // re-throw
                throw;
            }
            catch(SegmentationFault &)
            {
                cout << "SegmentationFault"<< endl;
            }
            catch(FloatingPointException &)
            {
                cout << "FloatingPointException"<< endl;
            }
            catch(...)
            {
                cout << "Unknown Exception" << endl;
            }
            //if this is a thread performing some core activity
            abort();
            // else if this is a thread used to service requests
            // pthread_exit();
        }
    };
public:
    ExceptionHandler()
    {
        staticSingleTonHandler s_objHandler;
    }
};
//////////////////////////////////////////////////////////////////////////
classA
{
public:
    A()
    {
        //int i = 0, j = 1/i;
        *(int*)0 = 0;
    }
};
// Before defining any global variable, we define a dummy instance
// of ExceptionHandler object to make sure that
// ExceptionHandler::SingleTonHandler::SingleTonHandler() is invoked
ExceptionHandler g_objExceptionHandler;
A g_a;
//////////////////////////////////////////////////////////////////////////
intmain(intargc, char* argv[])
{
    return0;
}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 在电脑中找不到想作废的发票怎么办 科目三补考费发票丢了怎么办 母婴店飞鹤奶粉突然厂家撤货怎么办 澳门买的保健品感觉是假的怎么办 淘宝买东西提交需求时卡死了怎么办 天猫精灵显示为离线状态怎么办 退货多被淘宝店铺拉入黑名单怎么办 天猫订单3天不发货怎么办 新开的厨卫店越来越没生意怎么办 淘宝积分不够领不到购物津贴怎么办 穿越火线精英集结号积分不足怎么办 天猫购物津贴领多了怎么办 车贷逾期车被开走还不清全款怎么办 孩子特别懒不爱动又胖怎么办 微信的聊天记录被限制了怎么办 门面租金交了一年对方不租了怎么办 离职后社保怎么办 无忧保专业可靠 淘宝店铺被投诉到监管局怎么办 淘宝买家每天都来店铺骚扰怎么办 电脑安装软件时解压出现问题怎么办 公婆不尊重你的父母做媳妇的怎么办 手机扣扣接收不上文件怎么办 买了商铺付了首付商铺倒闭了怎么办 宝宝刚满月不喜欢在床上睡怎么办 别人给我打了收货款不发货怎么办 业务员私收货款公司不发货怎么办 付款后商家没发货也不退钱怎么办 苹果7P修过主板耗电严重怎么办 oppo手机进水了开不了机怎么办 手机弯了变形但不影响使用怎么办 拼多多留错电话怎么办如果已经发货 苹果6手机后壳变形了怎么办 京东退货保修卡丢了怎么办 如果京东买的显示器屏碎了怎么办 在微信上买东西退货不退钱怎么办 手机分期付款不还款被起诉了怎么办 朋友用我的花呗分期不还钱怎么办 朋友用我身份证办分期不还钱怎么办 我手机号被别人绑定信用卡了怎么办 5s用不了4g网络怎么办 红米手机返回键没了怎么办