Я прочитал много статей о SEH exceptions
в StackOverflow и CodeProject.net.
После того, как я реализовал SEH exceptions
При обработке в моей C ++ программе на меня повлияло исключение переполнения стека, которое не было обнаружено моим программным обеспечением.
После следующей части исследования я понимаю, что программно невозможно обнаружить такое исключение, потому что у нас нет свободного адресного пространства стека, поэтому память программы повреждена.
Я хотел бы спросить вас о вашем опыте обработки исключения переполнения стека. Это выглядит как вызов, и мне действительно интересно, если это невозможно в языках программирования неуправляемого кода?
Ниже я представляю часть моей программы (C ++), которая воспроизводит stack overflow exception
, Это прекрасно работает для любого SEH exception
, но не переполнение стека:
LONG WINAPI SehHandler(PEXCEPTION_POINTERS pExceptionPtrs)
{
cerr << "Handled SEH exception!\n";
cerr << "ContextRecord: " << pExceptionPtrs->ContextRecord << endl;
cerr << "ExceptionRecord: " << pExceptionPtrs->ExceptionRecord << endl;
// Write minidump file
CreateMiniDump(pExceptionPtrs);
// Terminate process
TerminateProcess(GetCurrentProcess(), 1);
return EXCEPTION_EXECUTE_HANDLER;
}
int fib(unsigned int n) {
if(n == 0) return 0;
if(n == 1) return 1;
return fib(n-1)+fib(n-2);
}
int main(){
SetUnhandledExceptionFilter(SehHandler);
cout << fib(1000000);
return 0;
}
Да, вы можете получить мини-дамп из SO сбоев, но никогда так, как вы это делаете сейчас. Ваша функция SehHandler () выполняется в потоке, который вызвал исключение. И это в опасном состоянии, у вас осталось около 7080 байтов места для аварийного стека, чтобы сделать то, что вам нужно. Если вы потребляете это, то программа завершится с ошибкой с неуловимым нарушением прав доступа.
Вы не можете вызвать MiniDumpWriteDump () и надеяться выжить, эта функция требует больше стека, чем у вас есть. Так что это жесткий кабум без минидампа.
Тебе нужно другой поток, чтобы сделать этот вызов. Это может быть, например, поток, который вы создаете при инициализации и блокируете с помощью вызова WaitForMultipleObjects (). Ваш SehHandler () может вызвать SetEvent (), чтобы разбудить его. После записи значения PEXCEPTION_POINTERS в глобальную переменную. И блокировать на неопределенный срок, чтобы позволить потоку создать мини-дамп и прервать процесс.
Fwiw, безусловно, лучшее место для этой темы находится в другом процессе. Это также позволяет вам иметь дело с действительно неприятными, которые полностью портят состояние процесса. «Защитный» процесс, который вы запускаете при инициализации. С именованным событием, сигнализирующим об этом, и, скажем, отображенный в памяти файл для передачи PEXCEPTION_POINTERS. Не запускайте его в SehHandler (), куча процесса больше не надежна, поэтому CreateProcess () больше не может работать, вы должны сделать это рано.
Ответ Ханса Пассанта указывает, что существует 7080 байтов аварийного стека. Я не знаю, откуда эта информация, и он не ответил на @nop выше, и мои выводы показывают, что эта информация неверна. Однако этот сайт по какой-то причине не позволяет мне комментировать выше, поэтому я просто оставлю это здесь …
Есть функция, которая может использоваться для запроса и установки того, сколько аварийного стека осталось обработчику стека: SetThreadStackGuarantee()
. Обратите внимание, что с Windows 10 определенно (но я думаю, что с Windows 7, а также), в большинстве случаев это значение будет 0. Так что по умолчанию в обработчике нет ничего сложного. Вы можете быть в состоянии сигнализировать о другом потоке или внешнем процессе, как предложил Ганс, но это все.
Однако, если вы не хотите реализовывать такое сложное решение и можете сэкономить свободное место в стеке, его проще всего использовать. SetThreadStackGuarantee()
в установите для этого значения достаточно высокое, чтобы вы могли продолжить обработку исключения переполнения стека, как и любое другое. Обратите внимание, что вам нужно вызывать эту функцию в каждом потоке, который нуждается в этой функции, и вызывать ее до переполнение стека происходит, поэтому желательно при инициализации потока.