Pages Menu
Categories Menu

Опубликовано | Нет комментариев

Необработанные исключения

У всех потоков Windows имеется обработчик исключений, который занимается необработанными исключениями. Этот обработчик исключений объявляется внутренней Windows-функцией запуска потока (start-of-thread).

Эта функция запускается, когда пользователь создает процесс или любые дополнительные потоки. Она вызывает процедуру запуска потока, предоставляющего среду в контекстной структуре исходного потока, которая, в свою очередь, вызывает предоставляемую пользователем процедуру запуска потока, указанную в вызове CreateThread.

Просмотр реального пользовательского стартового адреса для Windows-потоков.

Тот факт, что каждый Windows-поток начинает свое выполнение с функции, предоставляемой системой (а не пользователем), объясняет, почему стартовый адрес для потока 0 одинаков для каждого Windows-процесса, имеющегося в системе (и почему стартовые адреса для вторичных потоков также одинаковы). Для просмотра адреса функции, предоставленной пользователем, нужно воспользоваться средством Process Explorer или отладчиком ядра.

Поскольку большинство потоков в Windows-процессах берут начало в одной из предоставленных системой функциях-оболочках, Process Explorer при отображении стартового адреса потока в процессе пропускает исходный фрейм вызова, представляющий функцию-оболочку, и вместо него показывает второй фрейм в стеке. Например, обратите внимание на стартовый адрес потока того процесса, в котором запущена программа Notepad.exe.

поток-процесса

Process Explorer при выводе стека вызовов выводит полную иерархию вызовов. Обратите внимание на следующие результаты, появляющиеся после щелчка на кнопке Stack.

стек-процесса

В строке 18 предыдущей копии экрана показан первый фрейм стека — стартовый адрес внутренней оболочки потока. Второй фрейм (строка 17) представляет собой оболочку потока подсистемы окружения — в данном случае kernel32, поскольку вы имеете дело с приложением подсистемы Windows. Третий фрейм (строка 16) представляет собой основную точку входа в Notepad.exe.

Общий код для стартовых функций внутреннего потока имеет следующий вид:

VOID RtlUserThreadStart(VOID)

{

LPVOID lpStartAddr = (R/E)AX; // Located in the initial thread context structure

LPVOID lpvThreadParam = (R/E)BX; // Located in the initial thread context structure

LPVOID lpWin32StartAddr;

lpWin32StartAddr = Kernel32ThreadInitThunkFunction ? Kernel32ThreadInitThunkFunction

: lpStartAddr;

__try

{

DWORD dwThreadExitCode = lpWin32StartAddr(lpvThreadParam);

RtlExitUserThread(dwThreadExitCode);

}

__except(RtlpGetExceptionFilter(GetExceptionInformation()))

{

NtTerminateProcess(NtCurrentProcess(), GetExceptionCode());

}

}

VOID Win32StartOfProcess(

LPTHREAD_START_ROUTINE lpStartAddr,

LPVOID lpvThreadParam)

{

lpStartAddr(lpvThreadParam);

}

Следует заметить, что фильтр необработанных исключений Windows вызывается в том случае, если у потока есть такое необработанное исключение. Цель данной функции заключается в предоставлении системно-независимого поведения при наличии необработанного исключения, которое выражается в запуске процесса WerFault.exe. Но в исходной конфигурации служба Windows Error Reporting, которая будет рассмотрена далее, обработает исключение, и этот фильтр необработанных исключений не будет задействован ни при каких условиях.

WerFault.exe проверяет содержимое параметра реестра HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug и убеждается в том, что процесс не находится в списке исключений. В этом параметре есть два важных значения: Auto и Debugger. Значение Auto сообщает фильтру необработанных исключений, нужно ли автоматически запускать отладчик, или же следует спросить у пользователя, что нужно делать.

Установка таких средств разработки, как Microsoft Visual Studio, изменяет это значение, если оно уже установлено, на 0. (Если значение не установлено, то 0 является настройкой по умолчанию.) Значение Debugger является строкой, указывающей путь к исполняемому отладчику для его запуска в случае наличия необработанного исключения, и WerFault передает ID аварийного процесса и имя события сигналу при запуске отладчика в виде аргументов командной строки, используемой для его запуска.

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.

↓