【Windows】【异常捕获】使用SetUnhandledExceptionFilter捕获异常,让程序自动重启,但是却在Release下无效

VergilYe 2017-12-04 04:42:16
这是我们公司的一个项目,要求在程序发生异常崩溃的时候,系统自动重启

百度了一下,发现SetUnhandledExceptionFilter可以指定一个回调函数,对异常进行处理.
所以我把重启的动作放到这个回调函数中.

代码具体如下:
回调函数:


LONG WINAPI ApplicationCrashHandler(EXCEPTION_POINTERS* pException)
{
AfxMessageBox(_T("注意:系统发生异常,将会自动进行重启!"));

//重启系统
system("shutdown -r -t 0 -f");


return EXCEPTION_EXECUTE_HANDLER;
}


在CXXXApp类的InitInstance()结尾处运行如语句:

void DisableSetUnhandledExceptionFilter()
{
void *addr = (void*)GetProcAddress(LoadLibrary(_T("kernel32.dll")), "SetUnhandledExceptionFilter");

if (addr)
{
AfxMessageBox(_T("DisableSetUnhandledExceptionFilter"));
unsigned char code[16];
int size = 0;
code[size++] = 0x33;
code[size++] = 0xC0;
code[size++] = 0xC2;
code[size++] = 0x04;
code[size++] = 0x00;

DWORD dwOldFlag, dwTempFlag;
VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
}
}
BOOL CXXXApp::InitInstance()
{
//指定异常处理的回调函数
SetUnhandledExceptionFilter(ApplicationCrashHandler);
//禁用SetUnhandledExceptionFilter,防止异常回调函数被覆盖.
DisableSetUnhandledExceptionFilter();
}



Debug模式下,是有效果的.
但是发现Release下,没有办法进入回调函数.
请教一下各位,如何解决这个问题?

系统是Win7,32位与64位都需要.
...全文
816 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
VergilYe 2017-12-26
  • 打赏
  • 举报
回复
引用 16 楼 zgl7903 的回复:
编程就应该养成良好的习惯, 不能完全依赖异常处理
我要这个功能,主要是为了让程序崩溃自动重启电脑,并使用dumpFile异地查看崩溃原因.
zgl7903 2017-12-23
  • 打赏
  • 举报
回复
编程就应该养成良好的习惯, 不能完全依赖异常处理
VergilYe 2017-12-23
  • 打赏
  • 举报
回复
目前使用SetUnhandledExceptionFilter函数能够成功捕获到异常了. 但是发现部分异常无法捕获. 例如: int *i; i = 1; delete []i; 上面的语句就捕获不到. 实在不想使用第三方库,有办法使用windows 自带API实现吗?
赵4老师 2017-12-23
  • 打赏
  • 举报
回复
http://blog.csdn.net/zhao4zhong1/article/details/53078924 老司机找bug的十年心路历程
zgl7903 2017-12-07
  • 打赏
  • 举报
回复
引用 9 楼 VergilYe 的回复:
[quote=引用 8 楼 zgl7903 的回复:] https://msdn.microsoft.com/en-us/library/windows/desktop/cc948909(v=vs.85).aspx
在网上找到这个实例: http://blog.csdn.net/tr0j4n/article/details/4633917 为啥我找不到RegisterApplicationRecoveryCallback函数. MSDN上明明写着WinBase.h(include Windows.h)... 我的系统是Win7,这个函数难道只有Vista可以用吗? 大哥,求指导...[/quote] targetver.h 中修改 平台定义 WINVER _WIN32_WINNT _WIN32_WINDOWS 0x0700 应该是WIN7
VergilYe 2017-12-07
  • 打赏
  • 举报
回复
引用 5 楼 jason_wentzel 的回复:
参考一下 http://blog.csdn.net/peter333666/article/details/1826123?locationNum=7
额,感觉这篇blog对我解决目前这个问题用处不大, MSJExceptionHandler这个类是自动输出程序崩溃的信息. 不过,这个功能倒是可以加进我的项目里... 非常感谢!
VergilYe 2017-12-07
  • 打赏
  • 举报
回复
引用 7 楼 wangningyu 的回复:
[quote=引用 楼主 VergilYe 的回复:] 这是我们公司的一个项目,要求在程序发生异常崩溃的时候,系统自动重启 百度了一下,发现SetUnhandledExceptionFilter可以指定一个回调函数,对异常进行处理. 所以我把重启的动作放到这个回调函数中. 代码具体如下: 回调函数:


LONG WINAPI ApplicationCrashHandler(EXCEPTION_POINTERS* pException)
{
	AfxMessageBox(_T("注意:系统发生异常,将会自动进行重启!"));

 	//重启系统
	system("shutdown -r -t 0 -f");

	
	return EXCEPTION_EXECUTE_HANDLER;
}
在CXXXApp类的InitInstance()结尾处运行如语句:

void DisableSetUnhandledExceptionFilter()
{
	void *addr = (void*)GetProcAddress(LoadLibrary(_T("kernel32.dll")), "SetUnhandledExceptionFilter"); 

	if (addr)  
	{ 
		AfxMessageBox(_T("DisableSetUnhandledExceptionFilter"));
		unsigned char code[16]; 
		int size = 0; 
		code[size++] = 0x33; 
		code[size++] = 0xC0; 
		code[size++] = 0xC2; 
		code[size++] = 0x04; 
		code[size++] = 0x00; 

		DWORD dwOldFlag, dwTempFlag; 
		VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag); 
		WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL); 
		VirtualProtect(addr, size, dwOldFlag, &dwTempFlag); 
	} 
}
BOOL CXXXApp::InitInstance()
{
	//指定异常处理的回调函数
	SetUnhandledExceptionFilter(ApplicationCrashHandler);
	//禁用SetUnhandledExceptionFilter,防止异常回调函数被覆盖.
	DisableSetUnhandledExceptionFilter();
}
Debug模式下,是有效果的. 但是发现Release下,没有办法进入回调函数. 请教一下各位,如何解决这个问题? 系统是Win7,32位与64位都需要.
调用的位置错了,这里调得太早,可能被其他模块覆盖了 放在Dlg OnInitDialog或者文档的CMainFrame::OnCreate中初始化 [/quote] 我发现,调试的位置没错..只是部分异常无效而已.. 可以看我前面的追问..
VergilYe 2017-12-07
  • 打赏
  • 举报
回复
引用 8 楼 zgl7903 的回复:
https://msdn.microsoft.com/en-us/library/windows/desktop/cc948909(v=vs.85).aspx
在网上找到这个实例: http://blog.csdn.net/tr0j4n/article/details/4633917 为啥我找不到RegisterApplicationRecoveryCallback函数. MSDN上明明写着WinBase.h(include Windows.h)... 我的系统是Win7,这个函数难道只有Vista可以用吗? 大哥,求指导...
再见理想~ 2017-12-07
  • 打赏
  • 举报
回复
https://www.codeproject.com/Articles/14618/Catch-All-Bugs-with-BugTrap 可以试下这个异常捕捉 工具
VergilYe 2017-12-07
  • 打赏
  • 举报
回复
引用 12 楼 zgl7903 的回复:
[quote=引用 9 楼 VergilYe 的回复:] [quote=引用 8 楼 zgl7903 的回复:] https://msdn.microsoft.com/en-us/library/windows/desktop/cc948909(v=vs.85).aspx
在网上找到这个实例: http://blog.csdn.net/tr0j4n/article/details/4633917 为啥我找不到RegisterApplicationRecoveryCallback函数. MSDN上明明写着WinBase.h(include Windows.h)... 我的系统是Win7,这个函数难道只有Vista可以用吗? 大哥,求指导...[/quote] targetver.h 中修改 平台定义 WINVER _WIN32_WINNT _WIN32_WINDOWS 0x0700 应该是WIN7 [/quote] targetver.h是空白的 只有这句 #include <SDKDDKVer.h> 我进去SDKDDKVer.h后,看到 #define _WIN32_WINNT_WIN7 0x0601 是把这个修改成0x0700吗? 但是,这个跟RegisterApplicationRecoveryCallback函数有什么关系?
VergilYe 2017-12-05
  • 打赏
  • 举报
回复
重新试了一下,发现触发不同的崩溃: (1) int *i; i[0]=1; (2) int *i; i[0]=1; delete i; 发现第一种是可以在Release模式下捕获的,而第二种,却弹出MS自带的异常处理对话框. 但是这两种崩溃都可以在Debug模式下捕获 有人知道其中的原理吗?
汪宁宇 2017-12-05
  • 打赏
  • 举报
回复
引用 楼主 VergilYe 的回复:
这是我们公司的一个项目,要求在程序发生异常崩溃的时候,系统自动重启 百度了一下,发现SetUnhandledExceptionFilter可以指定一个回调函数,对异常进行处理. 所以我把重启的动作放到这个回调函数中. 代码具体如下: 回调函数:


LONG WINAPI ApplicationCrashHandler(EXCEPTION_POINTERS* pException)
{
	AfxMessageBox(_T("注意:系统发生异常,将会自动进行重启!"));

 	//重启系统
	system("shutdown -r -t 0 -f");

	
	return EXCEPTION_EXECUTE_HANDLER;
}
在CXXXApp类的InitInstance()结尾处运行如语句:

void DisableSetUnhandledExceptionFilter()
{
	void *addr = (void*)GetProcAddress(LoadLibrary(_T("kernel32.dll")), "SetUnhandledExceptionFilter"); 

	if (addr)  
	{ 
		AfxMessageBox(_T("DisableSetUnhandledExceptionFilter"));
		unsigned char code[16]; 
		int size = 0; 
		code[size++] = 0x33; 
		code[size++] = 0xC0; 
		code[size++] = 0xC2; 
		code[size++] = 0x04; 
		code[size++] = 0x00; 

		DWORD dwOldFlag, dwTempFlag; 
		VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag); 
		WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL); 
		VirtualProtect(addr, size, dwOldFlag, &dwTempFlag); 
	} 
}
BOOL CXXXApp::InitInstance()
{
	//指定异常处理的回调函数
	SetUnhandledExceptionFilter(ApplicationCrashHandler);
	//禁用SetUnhandledExceptionFilter,防止异常回调函数被覆盖.
	DisableSetUnhandledExceptionFilter();
}
Debug模式下,是有效果的. 但是发现Release下,没有办法进入回调函数. 请教一下各位,如何解决这个问题? 系统是Win7,32位与64位都需要.
调用的位置错了,这里调得太早,可能被其他模块覆盖了 放在Dlg OnInitDialog或者文档的CMainFrame::OnCreate中初始化
赵4老师 2017-12-05
  • 打赏
  • 举报
回复
其实电脑开机后物理内存的每个字节中都有值且都是可读写的,从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页,一页通常为4KB。
VergilYe 2017-12-04
  • 打赏
  • 举报
回复
引用 2 楼 jzycode 的回复:
用GoogleBreakpad
有没有不需要第三方库的方法? 难道SetUnhandledExceptionFilter只能在Debug模式下生效吗?
_船长_ 2017-12-04
  • 打赏
  • 举报
回复
用GoogleBreakpad
oyljerry 2017-12-04
  • 打赏
  • 举报
回复
估计Release写的地址,code等有变化

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧