处理 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); } }; |
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; |
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; } |