EXCEPTEX 陷阱 MFC 和 Win32 结构例外

文章翻译 文章翻译
文章编号: 167802 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

概要

EXCEPTEX 是一个示例,演示补漏白的 Win32 结构化异常和 c + + 异常的方法。c + + 帮助各种程序提供了函数演示如何破解打开越常见的异常使用异常类。对于 Win32 结构化的异常帮助器函数是提供的标识的 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
    }
				
在基础差异是,c + + 异常处理需要捕获一个类型的实例,而 Win32 结构化异常处理捕捉只有三个无符号整数。

您可以但是,合并 c + + 和通过 _set_se_translator() 函数处理的 Win32 异常。这将导致 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 + + 类的指针,将引发异常。有 over-loaded 的版本 LogException 对于每个上面列出的 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 还跟踪文件的文件名和行号异常宏上次使用调用堆栈中 (如果使用帮助器日志宏)。

这些帮助器的每个工作破裂打开该异常,并将结果存储在一个字符串数组,如有必要,可以处理中。该函数用于转储到 TRACE() 宏此字符串数组的内容是 LogDisplay()。

简化 try/catch 块与帮助者宏

在代码中 littering try/catch 块可以获取杂乱后面一段。但是,就可以简化通过使用宏的异常块。EXCEPTEX 提供要简化这一过程的三个宏,并分别提供了不同的功能,用于日志记录/处理的异常。每个宏还写入 Visual c + + 4.X 和 Visual c + + 5.0,工作,因此它们必须检查的编译器所使用的版本。

下面是最简单的此的宏 LOGQ (安静异常处理无日志记录)。它需要一个名为 bRetVal 的布尔变量是在您的代码中可用。以便该宏可以允许执行可能会引发一个的异常的代码必须满足并将它设置为 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 版本。若要使用它们,添加 # 要使用 LOGE 或 LOGR 宏的文件中包括"log.h"。如果要破解 Win32 结构化异常,也必须调用 LogEnable 一次您的程序的开头附近。
   // One time initialization of data
    LogEnable(false);     // false to verbose mode
				
要异常从获取数据的代码中添加日志宏。
   ...
   LOGE(myFunction())
   ...
				
请注意,报告文件和行号将是最后的日志宏,在堆栈上。如果 myFunction() 调用 myFun1() 和 $ myFun2(),您必须将自动换行的每个宏的情况下日志输出显示中发生异常的调用的函数调用。

您可能不总是需要使用该日志的宏或甚至 LogException() 助手提供。它们提供的都是为了方便和作为嗯作为来演示全面的异常处理和用于记录结果的任何异常被捕获。未提供该的 end-all 异常处理中每个生产环境中进行所有作为。

故障排除

下面的代码演示如何不使用的帮助器宏
    LOGQ( int i = 0; )
    LOGQ( int j = 1 / i; )    // Will this raise a divide by zero?
				
此代码将生成编译器错误,如我只在第一个 LOGQ 宏的范围中定义的。请记住 LOGQ 扩展为:
>
    ...
    try
    {
        int i = 0;
    }
    ...

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

/ W4 和 # import

如果使用的 Visual c + + 和 # import /W4 标志,您将看到 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: return: 从 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 企业版
  • Microsoft Visual C++ 5.0 企业版
  • Microsoft Visual C++ 4.0 标准版
  • Microsoft Visual C++ 4.1 Subscription
  • Microsoft Visual C++ 4.2 专业版
  • Microsoft Visual C++ 5.0 专业版
关键字:?
kbmt kbdownload kbdatabase kbfile kbsample KB167802 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 167802
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。
不再更新的 KB 内容免责声明
本文介绍那些 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