EXCEPTEX 設陷 MFC 和結構化的 Win32 例外狀況

文章翻譯 文章翻譯
文章編號: 167802 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

結論

EXCEPTEX 是示範 Win32 結構化例外狀況和 C + + 例外狀況的補漏白的技術的範例。C + + 例外各種 Helper 函式提供示範如何破解開啟越常使用例外狀況類別。對於 Win32 結構化例外 Helper 函式是提供的識別 Win32 例外狀況擲回之型別。

從 「 Microsoft 下載中心 」 下載下列檔案有:


Exceptex.exe

如需有關如何下載 Microsoft 支援檔案的詳細資訊,按一下 [下列面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項]:
119591如何從線上服務取得 Microsoft 支援檔案
Microsoft 已掃描這個檔案有無病毒。Microsoft 使用已張貼檔案的日期中的 [可用的最新病毒偵測軟體。檔案儲存在安全性強化的伺服器上,以避免任何未經授權的更改至檔案。

其他相關資訊

合併 Win32 和 C + + 例外處理

C + + 例外處理和 Win32 結構化例外處理使用不同的語法設陷例外狀況。
    // C++ Exception Handler
    try
    {
        // Do something that may raise an exception
    }
    catch( <class name> <instance of class> )
    {
        // handle exception
    }

    // Win32 Structured Exception Handler
    __try
    {
        // Do something that may raise an exception
    }
    __except( expression )
    {
        // handle exception
    }
				
fundamental 差異在於以攔截一個型別的執行個體而只有三個不帶正負號的 ints Win32 結構化例外處理攔截預期的 C + + 例外處理。

您可以但是,C + + 和合併 Win32 例外狀況處理透過 _set_se_translator() 函式。這會讓 Win32 例外狀況會被傳送到處理常式函式,您選擇一個類別中包裝 Win32 例外狀況資訊,並擲它"回"作為一個 C + + 的例外狀況。自動發生何時 Win32 例外狀況發生於,並不著痕跡地似乎為 C + + 例外狀況的程式 (請參閱在 VC 5.0 infoviewer 例外狀況處理差異)。這是為您自動完成如果您使用記錄巨集,而且與相關支援 Log() 函式。
    // Class for containing information on a Win32 Structured Exception
    class SEH_Exception {
    private:
        SEH_Exception() {}
        unsigned int m_uSECode;
    public:
        SEH_Exception(unsigned int uSECode) : m_uSECode(uSECode) {}
        ~SEH_Exception() {}
        unsigned int getSeHNumber() { return m_uSECode; }
    };

    // Handler function that passes on Win32 Exception information in the
    // C++ class SEH_Exception
    void MappingSEHtoCPPExceptions( unsigned int uExceptionCode,
                                                  _EXCEPTION_POINTERS* )
    {
        throw SEH_Exception( uExceptionCode );
    }

    // Initialize Exception Handling
    void LogEnable( ... )
    {
        // Set Win32 Exceptions to be handled as C++ typed exceptions
        _set_se_translator(MappingSEHtoCPPExceptions);

        ...
    }
				
在這種情況下 LogEnable 會被呼叫一次、 盡早在程式的執行,引發任何 Win32 例外狀況可能會抓到與 C + + 語法。[EXCEPTEX 範例會示範這使用給定上述程式碼。

C + + 例外狀況的類型

有數種類別可以捕捉到由 MFC-基礎程式的 C + + 例外狀況:

  • 類別的執行個體衍生自 MFC 的 CException
  • 將封裝 Win32 類別的執行個體例外狀況
  • 執行個體的類別 _com_error Visual C++ 5.0 所引發的原生 COM 支援可以透過 # import 指示詞。
對於每一種,EXCEPTEX 會提供呼叫多載的被攔截到例外狀況之特定類型的 LogException 到函式。在每一種情況下執行個體或特定類型通常是 C + + 類別的指標,會引發例外狀況。有個 LogException over-loaded 針對每個以上所列的 C + + 例外狀況類型的版本。

下面是多載會攔截 MFC CException 類別的指標的 LogException 函式宣告的範例。
    // Crack open and log details of different types of exceptions
    extern void LogException( CException    *e,
                              LPCSTR        lpszTimeStamp,
                              LPCSTR        lpszFile,
                              int           nLine        );
				
LogException 也可以追蹤檔案的檔名和行號處例外巨集為您上一次使用呼叫堆疊中 (如果在使用 Helper 記錄巨集)。

每個這些協助程式 cracks 開放的例外狀況的函式,並將結果儲存在必要時可以處理的字串陣列。函式的傾印到 TRACE() 巨集這個字串陣列的內容是 LogDisplay()。

簡化 try/catch 區塊,以協助程式的巨集

在您的程式碼中 littering try/catch 區塊可以取得雜亂之後一段時間。但是,它有可能簡化透過巨集的使用例外狀況區塊。EXCEPTEX 提供三個巨集來簡化此程序,並每一個提供不同的記錄/處理的例外狀況的功能。每個巨集也會寫入適用於 Visual C++ 4.X 和 Visual 的 C + + 5.0,所以它們必須檢查您所使用的編譯器版本。

下面是最簡單的巨集 LOGQ (安靜例外處理以無記錄)。它所預期布林值變數,名為 bRetVal 位於您的程式碼。它必須是,則為 True,使該巨集可以允許執行可能引發的例外狀況的程式碼,而且它將它設定為 FALSE 如果引發例外狀況。
    #if _MSC_VER < 1100    // For version VC++ 4.2 or earlier

        #define LOGQ( f ) if( bRetVal == TRUE )                \ 
                          {                                    \ 
                             try                               \ 
                             {                                 \ 
                                 f;                            \ 
                             }                                 \ 
                             catch( CException *e )            \ 
                             {                                 \ 
                                bRetVal = FALSE;               \ 
                                 e->Delete();                  \ 
                             }                                 \ 
                             catch( SEH_Exception )            \ 
                             {                                 \ 
                                bRetVal = FALSE;               \ 
                             }                                 \ 
                             catch(...)                        \ 
                             {                                 \ 
                                bRetVal = FALSE;               \ 
                             }                                 \ 
                          }

    #else

        #define LOGQ( f ) if( bRetVal == TRUE )                \ 
                          {                                    \ 
                             try                               \ 
                             {                                 \ 
                                f;                             \ 
                             }                                 \ 
                             catch( CException *e )            \ 
                             {                                 \ 
                                bRetVal = FALSE;               \ 
                                e->Delete();                   \ 
                             }                                 \ 
                             catch( _com_error )               \ 
                             {                                 \ 
                                bRetVal = FALSE;               \ 
                              }                                \ 
                             catch( SEH_Exception )            \ 
                             {                                 \ 
                                bRetVal = FALSE;               \ 
                             }                                 \ 
                             catch(...)                        \ 
                             {                                 \ 
                                bRetVal = FALSE;               \ 
                             }                                 \ 
                          }

    #endif
				
# ifdef _MSC_VER 會限制能夠 Visual C++ 4.X 或 5.0 的特定巨集的定義。5.0 版包含 (由建立 # import 從程式碼所產生) 的新引入的 _com_error 例外狀況 catch。

您會使用 LOGQ,如下所示:
    int     i = 0;
    int     j;
    BOOL    bRetVal = TRUE;

    // This code is not safe
    j = 1 / i;        // Raises Win32 Divide By Zero exception

    // This code is safe
    LOGQ( j = 1 / i; )
				
有兩個版本的 EXCEPTEX 所提供的記錄巨集。 第二個記錄巨集使用多載上面所述的 LogException() 協助程式。
    #define LOGE( f ) try                               \ 
                      {                                 \ 
                          f;                            \ 
                      }                                 \ 
                      catch( CException *e )            \ 
                      {                                 \ 
                          LogException( e,              \ 
                                        __TIMESTAMP__,  \ 
                                        __FILE__,       \ 
                                        __LINE__      );\ 
                      }                                 \ 
                      ...
				
此巨集並不會讓使用的旗標 bRetVal。它永遠會執行巨集封裝程式碼、 攔截引發任何例外狀況並記錄其內容。

最終記錄巨集所提供的 EXCEPTEX LOGR,結合 LOGQ 和 LOGE 兩者。它會查看是否它應該執行的程式碼,並記錄,就會引發任何例外狀況。
    #define LOGR( f ) if( bRetVal == TRUE )                 \ 
                      {                                     \ 
                          try                               \ 
                          {                                 \ 
                              f;                            \ 
                          }                                 \ 
                          catch( CException *e )            \ 
                          {                                 \ 
                              LogException( e,              \ 
                                            __TIMESTAMP__,  \ 
                                            __FILE__,       \ 
                                            __LINE__      );\ 
                              bRetVal = FALSE;              \ 
                          }                                 \ 
                          ...
                        }
				

其他有用的功能

EXCEPTEX 範例提供三個更多的函式,來協助例外處理:
LogDisplay()傾印所有已記錄例外出透過 TRACE 巨集的內容。

LogDisplay (...)傾印的所有已記錄例外出 CListBox 的執行個體的內容。

LogSaveToFile (...)傾印的所有已記錄例外出到檔案的內容。

LOG.H 和 LOG.CPP

LOG.H 和 LOG.CPP 包含所有中 EXCEPTEX 處理的例外狀況的程式碼。其餘是範例的示範 LOG.H 和 LOG.CPP 中找到巨集/函數。這兩個檔案可以輕鬆地加入至現有的專案,並已寫入編譯中任一 Visual C++ 4.X 或 5.0 在 ANSI 和 UNICODE 建置。若要使用它們,加入 # 包括 log.h 」 將會使用 LOGE 或 LOGR 巨集的檔案。如果想也破解 Win32 結構化例外狀況必須呼叫 LogEnable 一次程式開端附近。
   // One time initialization of data
    LogEnable(false);     // false to verbose mode
				
在您想要取得例外狀況的資料的程式碼中加入記錄巨集。
   ...
   LOGE(myFunction())
   ...
				
報告檔和行號的附註會在堆疊上的最後一個記錄巨集。如果 myFunction() 呼叫 myFun1() 和 myFun2(),您必須換行與記錄巨集每個函式呼叫的輸出顯示例外狀況發生在哪一個呼叫。

您可能不一定要使用 [記錄巨集或甚至 LogException() 協助所提供。它們會提供兩者為方便和正如嗯來示範完整的例外處理,並記錄結果的任何例外狀況攔截到。它們不會提供作為的 end-all 在每個生產環境中處理的例外狀況的是所有。

疑難排解

下列程式碼將示範如何不使用 Helper 巨集
    LOGQ( int i = 0; )
    LOGQ( int j = 1 / i; )    // Will this raise a divide by zero?
				
i 是只中所定義範圍的第一個 LOGQ 巨集,這個程式碼會產生編譯器錯誤。請記住 LOGQ 展開以:
>
    ...
    try
    {
        int i = 0;
    }
    ...

    ...
    try
    {
        int j = 1 / i;  // error C2065: 'i' : undeclared
    }
    ...
				

/ W4 和 # import

如果您使用的 / W4 旗標,Visual C++ 和 # import 中的,您會看到 8 關閉 # import 利用包含檔案產生的警告。
comutil.h(905): 警告 C4310: 型別轉換會截斷常數值
comutil.h(928): 警告 C4310: 型別轉換會截斷常數值
comutil.h(1030): 警告 C4310: 型別轉換會截斷常數值
comutil.h(1281): 警告 C4310: 型別轉換會截斷常數值
comutil.h(1307): 警告 C4310: 型別轉換會截斷常數值
comutil.h(1476): 警告 C4310: 型別轉換會截斷常數值
comdef.h(242): 警告 C4244: '傳回': 從轉換 'int' 到 '簽署短'、 可能遺失的資料
這些錯誤訊息可以忽略,而且應該不會影響您的程式碼。

如需詳細資訊

下列的 VC + + 5.0 infoviewer 主題呈現良好的例外處理技術簡介:
例外處理: 常見問題集
mk:@ivt:vccore/F26/D2A/S31BE4.HTM

例外狀況處理差異
mk:@ivt:vccore/F26/D2B/S4CC99.HTM
下列文件示範可能被用來展開 EXCEPTEX 範例來處理 DAO SDK 的例外狀況的技術。
152695如何捕捉和破解 DAO SDK 為基礎的例外狀況
在找不到在 Win32 例外處理的明確來源:

由 Jeffrey Richter ISBN 1-57231-548-2 的 [進階的 Windows]

屬性

文章編號: 167802 - 上次校閱: 2004年8月5日 - 版次: 3.2
這篇文章中的資訊適用於:
  • Microsoft Visual C++ 4.2 Enterprise Edition
  • Microsoft Visual C++ 5.0 Enterprise Edition
  • Microsoft Visual C++ 4.0 Standard Edition
  • Microsoft Visual C++ 4.1 Subscription
  • Microsoft Visual C++ 4.2 Professional Edition
  • Microsoft Visual C++ 5.0 Professional Edition
關鍵字:?
kbmt kbdownload kbdatabase kbfile kbsample KB167802 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:167802
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。
依現狀不再更新的知識庫內容免責聲明
本文旨在說明 Microsoft 不再提供支援的產品。因此,本文係依「現狀」提供,不會再更新。

提供意見

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com