对于未处理异常,例如异常过滤返回EXCEPTION_CONTINUE_SEARCH,向上搜索,但无法搜索到处理部分,产生未处理异常。Windows提供了 SetUnhandledExceptionFilter 函数,给我们处理异常的最后机会,否则 Windows 会正式认为这个异常没有得到处理。

默认情况下,如果没有设置 SetUnhandledExceptionFilter 函数,对于未处理异常,会调用操作系统的默认异常处理代码 UnhandledExceptionHandler

通常应该在进程初始化阶段调用这个函数,一旦调用,进程中所有线程的未抛出异常都会导致 SetUnhandledExceptionFilter 参数所指定的的异常过滤函数的执行。

// 负责处理未处理异常
// 进程初始化时,设置处理未处理异常过滤函数
PTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(
PTOP_LEVEL_EXCEPTION_FILTER pTopLevelExceptionFilter
);

参数是一个异常过虑函数,原型必须与下面类似

// 返回值和结果
// EXCEPTION_EXECUTE_HANDLER 进程终止
// EXCEPTION_CONTINUE_EXECUTION 从抛出异常处再执行
// EXCEPTION_CONTINUE_SEARCH 不处理
LONG WINAPI TopLevelUnhandledExceptionFilter(
PEXCEPTION_POINTERS pExceptionInfo
);

C/C++运行函数安装的默认的全局异常过滤程序: __CxxUnhandledExceptionFilter,用 NULL 调用 SetUnhandledExceptionFilter 将全局未处理异常过滤程序设回 UnhandledExceptionFilter

#include <windows.h>
#include <stdio.h> long __stdcall callback(_EXCEPTION_POINTERS* excp)
{
MessageBox(0, "Error", "error", MB_OK); printf("Error address %x\n", excp->ExceptionRecord->ExceptionAddress);
printf("CPU register:\n");
printf("eax %x ebx %x ecx %x edx %x\n", excp->ContextRecord->Eax,
excp->ContextRecord->Ebx, excp->ContextRecord->Ecx,
excp->ContextRecord->Edx); return EXCEPTION_EXECUTE_HANDLER; // 进程终止
} int main(int argc, char* argv[])
{
PTOP_LEVEL_EXCEPTION_FILTER pException = SetUnhandledExceptionFilter(callback);
_asm int 3 // 只是为了让程序崩溃
return 0;
}

我们都知道,每个线程的执行都是从 NTDLL.dll 中的函数 BaseThreadStart 开始的:

VOID BaseThreadStart(
PTHREAD_START_ROUTINE pfnStartAddr,
PVOID pvParam
)
{
__try
{
ExitThread((pfnStartAddr)(pvParam));
}
__except (UnhandledExceptionFilter(GetExceptionInformation()))
{
ExitProcess(GetExceptionCode());
}
} // 上述UnhandledExceptionFilter的返回值和结果
// EXCEPTION_EXECUTE_HANDLER 执行ExitProcess,进程退出
// EXCEPTION_CONTINUE_EXECUTION 从抛出异常处再次执行
// EXCEPTION_CONTINUE_SEARCH 未处理异常

// 上述UnhandledExceptionFilter的返回值和结果
// EXCEPTION_EXECUTE_HANDLER 执行ExitProcess,进程退出
// EXCEPTION_CONTINUE_EXECUTION 从抛出异常处再次执行
// EXCEPTION_CONTINUE_SEARCH 未处理异常

如果我们的线程抛出一个异常,并且所有安装的异常过滤程序都返回 EXCEPTION_CONTINUE_SEARCH,系统提供的一个特殊函数 UnhandledExceptionFilter 将会被调用。

本书讨论的是用户态的开发。对内核态线程抛出未处理异常,在蓝屏前,系统让相关设备驱动调用 CrashDmp.sys在页文件中建立 Crash Dump,再停止所有操作。重启后,会查看页文件是否包含了一个 Crash Dump,如果有表示数据得到了存储 ,系统让WerFault运行,产生错误报告,并发送给Microsoft服务器。

24.1 SetUnhandledExceptionFilter未处理异常--《Windows核心编程》的更多相关文章

  1. C++Windows核心编程读书笔记

    转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...

  2. 【转】《windows核心编程》读书笔记

    这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...

  3. windows核心编程 - 线程同步机制

    线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...

  4. 【windows核心编程】 第八章 用户模式下的线程同步

    Windows核心编程 第八章 用户模式下的线程同步 1. 线程之间通信发生在以下两种情况: ①    需要让多个线程同时访问一个共享资源,同时不能破坏资源的完整性 ②    一个线程需要通知其他线程 ...

  5. 【windows核心编程】 第六章 线程基础

    Windows核心编程 第六章 线程基础 欢迎转载 转载请注明出处:http://www.cnblogs.com/cuish/p/3145214.html 1. 线程的组成 ①    一个是线程的内核 ...

  6. 《Windows核心编程》读书笔记 上

    [C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...

  7. 《windows核心编程系列》十六谈谈内存映射文件

    内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟内存不同的是,内存映射文件的物理存储器来自磁盘中的文件,而非系统的页交换文件.将文件映射到内存中后,我们就可以在内存中操作他们了 ...

  8. windows核心编程---第八章 使用内核对象进行线程同步

    使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...

  9. windows核心编程-互斥器(Mutexes)

    线程同步的方式主要有:临界区.互斥区.事件.信号量四种方式. 前边讲过了临界区线程同步-----windows核心编程-关键段(临界区)线程同步,这章我来介绍一下互斥器(Mutexes)在线程同步中的 ...

  10. 【Windows】windows核心编程整理(上)

    小续 这是我11年看<windows核心编程>时所作的一些笔记,现整理出来共享给大家 windows核心编程整理(上) windows核心编程整理(下) 线程的基础知识 进程是不活泼的,进 ...

随机推荐

  1. webservice(AXIS)客户端生成方法

    如何根据apache的axis生成的WebServices服务接口生成客户端代码一.下载axis-bin-1_4.zip    官网下载地址:    https://mirrors.bfsu.edu. ...

  2. uniapp picker组件实现二级联动

    https://blog.csdn.net/hxh_csdn/article/details/111504951 https://www.cnblogs.com/jstll/p/14149600.ht ...

  3. kibana上执行ES DSL语言查询数据并查看表结构与数据、删除索引、查看文件大小

    转载请注明出处: 1.kibana 上执行DSL 语言: 在kibana 中找到 Dev Tools,并双击打开,就可以进入执行DSL得执行页面了 执行DSL,示例如图: 2.在kibana上查看ES ...

  4. Pgsql之查询一段时间内的所有年月yyyy-mm

    前几天干活儿的时候,报表中有这么个需求,需要用pgsql查询两个日期间的所有年月,下面贴代码: 1 with recursive t(n) as ( 2 select date('2020-01-01 ...

  5. 关于spring-boot-starter-parent 3.1.2和3.1.5版本的区别导致的错误

    1.问题 在学习黑马程序员SpringBoot3+Vue3全套视频教程时,手动配置springboot项目时,由于之前spring-boot-starter-parent安装的版本是3.1.5,视频要 ...

  6. 【Linux】技术收集

    Linux进程间通信(六)---信号量通信之semget().semctl().semop()及其基础实验 https://blog.csdn.net/mybelief321/article/deta ...

  7. 【中介者模式(Mediator)】使用Java实现中介者模式

    引言 中介者,何为中介者,顾名思义就是我们的在处理A和B之间的关系的时候,引入一个中间人,来处理这两者之间的关系,例如生活中我们需要去租房,买房,都会有中介,来处理房东和租客之间的协调关系,这个就是中 ...

  8. [转帖]A Quick Look at the Huawei HiSilicon Kunpeng 920 Arm Server CPU

    https://www.servethehome.com/a-quick-look-huawei-hisilicon-kunpeng-920-arm-server-cpu/     Huawei Hi ...

  9. [转帖] 原来awk真是神器啊

    https://www.cnblogs.com/codelogs/p/16060082.html 简介# 刚开始入门awk时,觉得awk很简单,像是一个玩具,根本无法应用到工作之中,但随着对awk的了 ...

  10. 【解决了一个小问题】macbook m2 下交叉编译 musl-gcc 支持的 gozstd 库

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 我的 golang 项目中使用了 gozstd, 在 ma ...