【厚积薄发系列】C++项目总结14—Windows平台下异常捕获不到问题分析

本文探讨了Windows XP系统上异常捕获不全的问题,并提供了一种通过修改内核函数来确保全局异常处理机制有效性的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题背景:

Windows平台常用的异常捕获函数有时候不起作用,特别是XP系统上,有些runtime error捕获不到,但是其他系统如win7、win8等又能正常捕获,导致产品发出去后遇到这类异常,莫名其妙的弹一个错误框出来导致用户体验特别不好。

问题解决:

windows平台win32提供的常用捕获异常的接口有下面三种:

_set_invalid_parameter_handler(MyInvalidParameterHandler);

_set_purecall_handler(MyPureCallHandler);

SetUnhandledExceptionFilter(doSomething);

这上面三个win32的接口参数可以设置自己的回调函数,及遇到异常后开发可以做最后的处理,如生成dump文件、启动报警机制等等。上面三个函数的设置后能捕获系统SEH异常和CRT异常。但是程序在XP系统上或者其他系统上会出现设置了全局的SetUnhandledExceptionFilter,却捕获不到子线程或者子模块的CRT异常,还是会弹出系统默认的错误框。

之所以还弹出默认的错误框,因为设置的全局捕获函数没起作用而是调用了系统默认的SetUnhandledExceptionFilter,开发自己设置SetUnhandledExceptionFilter() 时,是将用户注册的函数地址存到全局变量 kernel32!BasepCurrentTopLevelFilter 中,而捕获不到异常的时候发现自己设置的函数地址和系统触发的地址不一样,说明系统调用了默认的。为了解决上面注册了全局捕获函数而捕获不到子模块子线程异常的问题,这里可以采用人工代码打补丁的方式来解决,需要自己实现一个打补丁函数,在设置全局捕获函数后手动调用打补丁函数,实例代码如下:

SetUnhandledExceptionFilter(doSomething);

PatchSetUnhandledExceptionFilter()  //打补丁的具体实现如下

void PatchSetUnhandledExceptionFilter()
{
static BYTE RETURN_CODE[] = { 0xc2, 0x04, 0x00}; 
MEMORY_BASIC_INFORMATION   mbi;
DWORD dwOldProtect = 0;
DWORD pfnSetFilter =(DWORD)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetUnhandledExceptionFilter");
VirtualQuery((void *)pfnSetFilter, &mbi, sizeof(mbi) );
VirtualProtect( (void *)pfnSetFilter, sizeof(RETURN_CODE), PAGE_READWRITE, &dwOldProtect);
//VirtualProtectEx(GetCurrentProcess(), (void *)pfnSetFilter, sizeof(RETURN_CODE), PAGE_READWRITE, &dwOldProtect);
//如64系统下VirtualProtect后WriteProcessMemory崩溃,则用VirtualProtectEx
WriteProcessMemory(GetCurrentProcess(), (void *)pfnSetFilter,RETURN_CODE,sizeof(RETURN_CODE), NULL);
VirtualProtect((void *)pfnSetFilter, sizeof(RETURN_CODE), mbi.Protect, 0); 
//VirtualProtectEx(GetCurrentProcess(),(void *)pfnSetFilter, sizeof(RETURN_CODE), mbi.Protect, 0); 
FlushInstructionCache(GetCurrentProcess(), (void *)pfnSetFilter, sizeof(RETURN_CODE));

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值