• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    Linux下 C++程序的異常處理技巧

    發布: 2007-7-04 12:06 | 作者: admin | 來源:  網友評論 | 查看: 20次 | 進入軟件測試論壇討論

    領測軟件測試網   處理 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 &)
         {
          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;
      }
      處理多線程程序中的異常

      有時一些異常沒有被捕獲,這將造成進程異常中止。不過很多時候,進程包含多個線程,其中少數線程執行核心應用程序邏輯,同時,其余線程為外部請求提供服務。如果服務線程因編程錯誤而沒有處理某個異常,則會造成整個應用程序崩潰。這一點可能是不受人們歡迎的,因為它會通過向應用程序傳送不合法的請求而助長拒絕服務攻擊N?吮苊庹庖壞悖?床痘翊?沓絳蚩梢躍齠ㄊ喬肭笠斐V兄溝饔茫?故喬肭笙叱掏順齙饔謾G宓?3 中 ExceptionHandler::SingleTonHandler::Handler() 函數的末尾處展示了該處理程序。

      結束語

      我簡單地討論了少許 C++ 編程設計模式,以便更好地執行以下任務:

      ·在拋出異常的時候追蹤異常的來源。
      ·將信號從內核程序轉換成 C++ 異常。
      ·捕獲構造和/或析構全局變量期間拋出的異常。
      ·多線程進程中的異常處理。

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>