При каких обстоятельствах EXCEPTION_RECORD ссылается на другое вложенное исключение?

Документация для _EXCEPTION_RECORD говорит об одном из его членов, struct _EXCEPTION_RECORD *ExceptionRecord

Указатель на связанную структуру EXCEPTION_RECORD. Записи об исключениях могут быть объединены в цепочку для предоставления дополнительной информации при возникновении вложенных исключений.

Однако я не смог спровоцировать такую ​​ситуацию с вложенными структурированными исключениями. Вот что я пробовал до сих пор:

#include <iostream>
#include <windows.h>

void Handle0(LPEXCEPTION_POINTERS pex) {
    std::cout << "chain0 = " << pex->ExceptionRecord->ExceptionRecord << std::endl;
}

void Handle1(LPEXCEPTION_POINTERS pex) {
    std::cout << "chain1 = " << pex->ExceptionRecord->ExceptionRecord << std::endl;
    __try {
        throw 3;
    } __except( Handle0(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER ) {}
}

int main() {
    __try {
        throw 3;
    } __except( Handle1(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER ) {}
    return 0;
}

pex->ExceptionRecord->ExceptionRecord всегда nullptr, При каких обстоятельствах я получаю ссылку на вложенный _EXCEPTION_RECORD там?

0 ответов

Согласно MSDN:

Когда исключение возникает во время обработки фильтра исключений в... машинном коде... возникает вложенное исключение,ExceptionRecord поле в EXCEPTION_RECORD структура (возвращенная GetExceptionInformation) установлен, а ExceptionFlags поле устанавливает 0x10немного. Следующий пример иллюстрирует эту разницу в поведении:

#include <windows.h>
#include <stdio.h>
#include <assert.h>

#ifndef false
#define false 0
#endif

int *p;

int filter(PEXCEPTION_POINTERS ExceptionPointers) {
   PEXCEPTION_RECORD ExceptionRecord =
                     ExceptionPointers->ExceptionRecord;

   if ((ExceptionRecord->ExceptionFlags & 0x10) == 0) {
      // not a nested exception, throw one
      *p = 0; // throw another AV
   }
   else {
      printf("Caught a nested exception\n");
      return 1;
    }

   assert(false);

   return 0;
}

void f(void) {
   __try {
      *p = 0;   // throw an AV
   }
   __except(filter(GetExceptionInformation())) {
      printf_s("We should execute this handler if "
                 "compiled to native\n");
    }
}

int main() {
   __try {
      f();
   }
   __except(1) {
      printf_s("The handler in main caught the "
               "exception\n");
    }
}

Я считаю, что он также установлен, если вы попытаетесь продолжить непродолжаемое исключение. В этом случаеEXCEPTION_RECORD будет представлять EXCEPTION_NONCONTINUABLE_EXCEPTION, а его ExceptionRecord укажет на исходное исключение.

Другие вопросы по тегам