Linux下C 异常处理技巧-实例讲解

2008-02-23 05:41:41来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折


  保留异常来源信息

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

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

  清单 1. 在异常对象构造函数中生成一个堆栈跟踪

  // Sample Program:

  // Compiler: gcc 3.2.3 20030502

  // Linux: Red Hat

  #include

  #include

  #include

  #include

  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 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 g_objSegmentationFaultTranslator;

  // An example for SIGFPE

  class FloatingPointException : public ExceptionTracer, public exception

  {

  public:

  static int GetSignalNumber() {return SIGFPE;}

  };

  SignalTranslator 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

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 使用TC实现基于linux的流量管理

下一篇: Linux下C语言编程--时间概念