異常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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM