C 程式的异常处理技巧

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

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

  处理 C 中的异常会在语言级别上碰到少许隐含限制,但在某些情况下,您能够绕过他们。学习各种利用异常的方法,您就能够生产更可靠的应用程式。

  保留异常来源信息

  在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 &)

标签:

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

上一篇: C 中extern “C”含义深层探索

下一篇: Linux系统下搭建C/C 研发的IDE环境