技术演进中的开发沉思-25 window编程系列:异常处理

作为程序员,我们最早接触异常处理时,总觉得只要把代码 “try 起来”,就像给程序穿上了一层防护甲。就好比在搭建一座积木城堡,把那些可能会倒塌(出现错误)的部分,用透明罩子罩起来,以为这样就能高枕无忧。但真正深入 Windows 编程的世界后,我才发现,异常处理远不止表面这么简单,它是一套精密而复杂的系统,有着自己独特的运行逻辑和使命。

一、异常处理的 “双保险” 机制

在 Windows 编程的世界里,异常过滤程序和异常处理程序就像守护程序安全的两道防线。想象你在驾驶一辆汽车,异常过滤程序如同路口的交通信号灯,先判断异常的 “路况” 是否需要紧急处理;而异常处理程序则是路边的维修站,负责真正解决问题。

我们通过funcmeister1和funcmeister2这两个函数来看看它们如何配合工作。在funcmeister1函数中,就像一个新手司机开车上路,可能会因为不熟悉路况(代码逻辑)而遇到各种意外(异常)。当异常发生时,异常过滤程序首先介入,它会根据异常的类型和条件,判断是直接处理这个异常,还是把问题 “移交” 给更上层的处理机制。


LONG WINAPI ExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo) {

if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {

// 这里可以做一些简单的判断和处理,比如记录日志

return EXCEPTION_CONTINUE_SEARCH;

}

return EXCEPTION_CONTINUE_SEARCH;

}

void funcmeister1() {

__try {

// 这里模拟可能会产生异常的代码

int* p = NULL;

*p = 1;

}

__except (ExceptionFilter(GetExceptionInformation())) {

// 异常处理代码

MessageBox(NULL, TEXT("异常已处理"), TEXT("提示"), MB_OK);

}

}

而funcmeister2函数则像是一位经验丰富的老司机,它的异常过滤程序更加智能,能够更准确地判断异常情况,做出更合适的处理决策。比如在处理不同类型的异常时,根据具体情况选择修复问题(让程序继续执行),或者安全地结束程序,避免造成更严重的后果。


LONG WINAPI AnotherExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo) {

if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {

// 尝试修复问题

return EXCEPTION_CONTINUE_EXECUTION;

}

return EXCEPTION_CONTINUE_SEARCH;

}

void funcmeister2() {

__try {

int* p = NULL;

*p = 1;

}

__except (AnotherExceptionFilter(GetExceptionInformation())) {

MessageBox(NULL, TEXT("异常已处理"), TEXT("提示"), MB_OK);

}

}

这两个函数就像不同性格的司机,面对异常时采取不同的应对策略,生动地展示了异常过滤程序和异常处理程序的协作过程。

二、异常处理的 “特殊指令”

在异常处理的工具箱里,有几条 “特殊指令”,它们各自有着独特的功能,就像医生手中不同的医疗器械,在处理异常时发挥着关键作用。

1、EXCEPTION_EXECUTE_HANDLER

EXCEPTION_EXECUTE_HANDLER就像是医生为病人制定的常规治疗方案。当异常发生且异常过滤程序返回EXCEPTION_EXECUTE_HANDLER时,程序会严格按照预设的异常处理代码执行,就像病人按照医嘱按时服药、接受检查一样。在实际编程中,它常常用于处理一些常见的、有固定处理方式的异常情况。例如,当程序遇到文件读取错误时,我们可以使用EXCEPTION_EXECUTE_HANDLER来执行关闭文件、提示用户重新选择文件等操作。

2、EXCEPTION_CONTINUE_EXECUTION

EXCEPTION_CONTINUE_EXECUTION仿佛拥有神奇的修复魔法,它告诉程序:“刚刚的问题已经解决了,可以继续前进了!” 当我们在异常过滤程序中判断异常已经被成功修复,比如修正了一个错误的内存指针指向,就可以返回EXCEPTION_CONTINUE_EXECUTION,让程序从异常发生的位置继续执行,就像汽车在故障排除后重新启动,沿着原来的路线继续行驶。

3、EXCEPTION_CONTINUE_SEARCH

有时候遇到复杂的异常情况,当前的异常处理机制无法解决,这时就需要EXCEPTION_CONTINUE_SEARCH来发挥作用。它就像把病人转诊到更专业的医院,进行 “专家会诊”。当异常过滤程序返回EXCEPTION_CONTINUE_SEARCH时,系统会继续在更上层的异常处理机制中寻找能够处理该异常的方案,直到找到合适的解决办法或者最终无法处理导致程序崩溃。

三、探秘异常的 “身份信息”

在处理异常时,了解异常的 “身份信息” 至关重要,就像医生需要知道病人的详细病情才能对症下药。GetExceptionCode和GetExceptionInformation这两个函数就像是异常的 “身份证” 和 “病历本”。

GetExceptionCode返回的是异常的类型代码,它就像给异常贴上了一个标签,告诉我们遇到的是内存访问违规(EXCEPTION_ACCESS_VIOLATION)、除零错误(EXCEPTION_DIVIDE_BY_ZERO)还是其他类型的问题。而GetExceptionInformation则提供了更详细的异常信息,包括异常发生的地址、相关的寄存器状态等,就像一份完整的病历,帮助我们深入分析异常产生的原因,从而制定更有效的解决方案。


LONG WINAPI ExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo) {

DWORD exceptionCode = ExceptionInfo->ExceptionRecord->ExceptionCode;

if (exceptionCode == EXCEPTION_ACCESS_VIOLATION) {

// 根据具体异常信息进行处理

CONTEXT* context = ExceptionInfo->ContextRecord;

// 可以进一步分析寄存器状态等信息

}

return EXCEPTION_CONTINUE_SEARCH;

}

四、软件异常:程序世界的 “意外插曲”

软件异常就像是程序世界里突如其来的 “意外插曲”,它们可能由各种原因引发,就像生活中突然的意外状况。可能是程序员不小心写错了一行代码,导致内存访问出错;也可能是用户的不当操作,触发了程序中未考虑到的逻辑漏洞;甚至可能是硬件故障,影响了程序的正常运行。

但正是这些看似讨厌的异常,推动着我们不断完善程序。每一次处理异常的过程,都像是在和程序进行一场深度对话,了解它的弱点,修复它的缺陷。从桌面开发到如今的微服务时代,异常处理技术也在不断演进,但它守护程序稳定运行的使命始终未变。

最后小结​

Windows 异常处理程序,是保障程序稳定运行的幕后英雄。从异常过滤程序与异常处理程序的 “双保险” 协作,到EXCEPTION_EXECUTE_HANDLER、EXCEPTION_CONTINUE_EXECUTION 等特殊指令的精准调控,再到获取异常 “身份信息” 的关键函数,每一个环节都不可或缺。软件异常虽常带来困扰,却也成为程序进化的阶梯。未完待续.........

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值