嵌套的__try ..__除外,这是如何工作的

Nested __try...__except clauses, how does this work?

本文关键字:何工作 工作 try 除外 嵌套      更新时间:2023-10-16

我正在处理一个函数和一个子函数,在函数中调用子函数。两者都有一个 __try .. __except-阶段,我想在功能中查看一般异常处理,而在子函数的情况下,特定的例外处理,换句话说:

int function(){
__try{
  do_something();
  return subfunction();
  } __except (Exception_Execute_Handler_Something()){
  show("general exception");
  }
int subfunction(){
  __try{
    return do_something_else();
  } __except (Exception_Execute_Handler_Something_Else()){
    show("specific case");
  }

在这种情况下:
do_something()出错时,我会看到"常规异常"。
do_something_else()出错时,我也会看到"一般异常",这不是我想要的。

我想要的是:
do_something()出错时,我想查看"常规异常。
do_something_else()出错时,我想看"特定情况"。

Ben Voight的备注之后编辑

确实有一个异常过滤器,目前正在检查确定是否继续的异常代码,如您在此处看到的那样:

if (Exception->ExceptionCode == STATUS_ACCESS_VIOLATION)
  return EXCEPTION_CONTINUE_SEARCH;
但是,我对ExceptionRecordContextRecord的结构和/或内容根本没有任何知识,即异常处理的两个输入参数。在此,我在特殊情况下举例说明这些参数的样子:

例外记录:

-   ExceptionRecord 0x0eecdec8 {ExceptionCode=3221225620 ExceptionFlags=0 ExceptionRecord=0x00000000 <NULL> ...}    _EXCEPTION_RECORD *
    ExceptionCode   3221225620  unsigned long // I guess this means division by zero
    ExceptionFlags  0   unsigned long
+   ExceptionRecord 0x00000000 <NULL>   _EXCEPTION_RECORD *
    ExceptionAddress    0x002c1993 {<Application>.exe!CClass::Main_Method(CInputClass & params), Line 46}   void *
    NumberParameters    0   unsigned long
+   ExceptionInformation    0x0eecdedc {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}    unsigned long[15]

contextrecord:

-   ContextRecord   0x0eecdf18 {ContextFlags=65543 Dr0=0 Dr1=0 ...} _CONTEXT *
    ContextFlags    65543   unsigned long
    Dr0 0   unsigned long
    Dr1 0   unsigned long
    Dr2 0   unsigned long
    Dr3 0   unsigned long
    Dr6 0   unsigned long
    Dr7 0   unsigned long
-   FloatSave   {ControlWord=0 StatusWord=0 TagWord=0 ...}  _FLOATING_SAVE_AREA
    ControlWord 0   unsigned long
    StatusWord  0   unsigned long
    TagWord 0   unsigned long
    ErrorOffset 0   unsigned long
    ErrorSelector   0   unsigned long
    DataOffset  0   unsigned long
    DataSelector    0   unsigned long
+   RegisterArea    0x0eecdf50 ""   unsigned char[80] // all are zero
    Spare0  0   unsigned long
    SegGs   43  unsigned long
    SegFs   83  unsigned long
    SegEs   43  unsigned long
    SegDs   43  unsigned long
    Edi 80923496    unsigned long
    Esi 250405956   unsigned long
    Ebx 0   unsigned long
    Edx 0   unsigned long
    Ecx 0   unsigned long
    Eax 1   unsigned long
    Ebp 250405884   unsigned long
    Eip 2890131 unsigned long
    SegCs   35  unsigned long
    EFlags  66118   unsigned long
    Esp 250405880   unsigned long
    SegSs   43  unsigned long
+   ExtendedRegisters   0x0eecdfe4 "x2 x1"    unsigned char[512] // at first sight, not readable

现在我的问题变成了:

如果我已经在另一个__try..__except子句中,我将return EXCEPTION_CONTINUE_SEARCH

有人知道我可以用来确定我是否已经在另一个__try..__except子句中的ExceptionRecordContextRecord属性中的哪个?

再次进行新的编辑,后再进行一些更多信息

我刚刚在C:Program Files (x86)Microsoft Visual Studio2017ProfessionalVCToolsMSVC14.16.27023includeexcpt.h中找到了EXCEPTION_DISPOSITION。这包含函数_except_handler(),该函数返回EXCEPTION_DISPOSITION枚举,可以是ExceptionNestedException(我相信这是我正在寻找的(。
所以现在问题变成了:

我需要填写哪些参数_except_handler()才能知道我是否正在处理嵌套异常(或者有人知道一种更简单的方法来完成此操作(?

书面的代码不会编译。而不是:

__except { ... }

您需要:

__except (EXCEPTION_EXECUTE_HANDLER) { ... }

然后根据需要起作用。

实时演示

#include <iostream>
#include <Windows.h>
int do_something_else()
{
    *(reinterpret_cast<int*>(0)) = 1;
    return 0;
}
int do_something()
{
    return 0;
}
int subfunction();
int32_t ReportCrash(LPEXCEPTION_POINTERS ExceptionInfo) //exception and context pointers are hrere
{
    return EXCEPTION_EXECUTE_HANDLER;
}
int function()
{
    __try 
    {
        do_something();
        return subfunction();
    }
    __except (ReportCrash(GetExceptionInformation()))
    {
        std::cout << ("general exception");
    }
    return 0;
}
int subfunction()
{
    __try 
    {
        return do_something_else();
    }
    __except (ReportCrash(GetExceptionInformation()))
    {
        std::cout << ("specific case");
    }
    return 0;
}
int main()
{
    std::cout << "Hello World!n"; 
    function();
}

详细信息在这里

您可以使用raiseexception。

#define SUBCODE 0x1000
int Filter(LPEXCEPTION_POINTERS exceptionPointers,DWORD& code) {
  code = exceptionPointers->ExceptionRecord->ExceptionCode;
  return EXCEPTION_EXECUTE_HANDLER;
}
int function(){
  DWORD code;
  __try{
      do_something();
      return subfunction();
    } __except ( Filter( GetExceptionInformation(), code )  ){  
      if (code == SUBCODE) {
        show("specific case");      
      } else {
        show("generic code");
      }
    }
}
int subfunction(){
  __try{
    return do_something_else();
  } __except (EXCEPTION_EXECUTE_HANDLER){
    RaiseException( SUBCODE , 0, 0 , NULL );
  }
}

exception_record结构具有一个名为exceptionRecord的成员,它是另一个exception_record的指针...这就是您告诉您是否已经嵌套异常的方式。