异常0xc000041d的抛出过程

为了说明这个过程,我们必须写一个示例程序,如下:

#include "stdafx.h"
#include <tchar.h>
#include <stdio.h>
#include <Windows.h>

#pragma comment(lib, "user32")

WNDPROC oldproc = NULL;

LRESULT CALLBACK newproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    throw 0;
    return oldproc(hwnd, uMsg, wParam, lParam);
}

int _tmain(int argc, TCHAR *argv[])
{
    HWND hWnd = CreateWindowEx(0, TEXT("STATIC"), TEXT("Name"),
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, NULL, NULL);
    oldproc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)newproc);
    
        UpdateWindow(hWnd);

    
        system("pause");
}

将上面的程序在vs建立工程编译运行,得到如下结果

 

 退出,在vs里按下快捷建F11,程序中断后,给函数ZwRaiseException下断点

 

 按F5运行程序,程序中断,观察到程序停在了_NtRaiseException@12

 

看下调用栈

 

可以看到此时正在抛出第一个异常,也就是真正的异常 throw 0;

按F5 继续运行程序,程序又中断了,可以看到此时又中断在_NtRaiseException@12,看下栈

 

这是第二次抛出异常,也就是抛出0xc000041d,我们观察下函数ntdll.dll!_LdrpLogFatalUserCallbackException@8() 

在这里里,填充了EXCEPTION_RECORD结构,紧接着调用了_NtRaiseException@12抛出异常。

简单来说,当程序产生了一个异常,首先走的还是正常的异常分发流程,当没有得到处理,又是在Windows系统的用户回调里发生的,会分发给_KiUserCallbackExceptionHandler去处理,_KiUserCallbackExceptionHandler里会调用_LdrpLogFatalUserCallbackException,_LdrpLogFatalUserCallbackException里会重新填充EXCEPTION_RECORD结构抛出异常0xc000041d。

posted on 2019-12-12 11:29  活着的虫子  阅读(5280)  评论(0编辑  收藏  举报

导航