程序崩溃优雅退出之-SetUnhandledExceptionFilter

Posted 小哈龙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序崩溃优雅退出之-SetUnhandledExceptionFilter相关的知识,希望对你有一定的参考价值。

1.百度百科

设置异常捕获函数.

当异常没有处理的时候,系统就会调用SetUnhandledExceptionFilter所设置异常处理函数.

例如一些程序在出错的时候,会向用户报告说程序那出错就是利用这个.例如QQ..

异常处理中的一部分

当发生异常时,比如内存访问违例时,CPU硬件会发现此问题,并产生一个异常(你可以把它理解为中断)

然后CPU会把代码流程切换到异常处理服务例程。操作系统异常处理服务例程会查看当前进程是否处于调试状态

如果是,则通知调试器发生了异常,如果不是则操作系统会查看当前线程是否安装了的异常帧链(FS[0]),如果安装了SEH(try.... catch....),则调用SEH,并根据返回结果决定是否全局展开或局部展开。如果异常链中所有的SEH都没有处理此异常,而且此进程还处于调试状态,则操作系统会再次通知调试器发生异常(二次异常)。如果还没人处理,则调用操作系统的默认异常处理代码UnhandledExceptionHandler,不过操作系统允许你Hook这个函数,就是通过SetUnhandledExceptionFilter函数来设置。大部分异常通过此种方法都能捕获,不过栈溢出、覆盖的有可能捕获不到。

大部分保护壳都采用异常处理技术,跳出正常的代码指令流程,来迷惑Cracker。

2.网络文章参考:

window下使用SetUnhandledExceptionFilter捕获让程序的崩溃_bingqingsuimeng的专栏-CSDN博客_setunhandledexceptionfilter

简单使用SetUnhandledExceptionFilter()函数让程序优雅崩溃

虽然是大公司的产品,QQ它还是会在我们的折腾下崩溃的,但是它总是崩溃的很优雅,还要弹出自己的对话框来结束。并且发送报告,去掉了系统默认的发送报告的对话框。

所以一拍脑袋,想让自己的程序崩溃的体面一点。

自己想了大概的思路,觉得可以用一个进程来监控目标程序。的确也可以拿到了目标程序崩溃的信息,知道它什么时候崩溃的,也可以做额外的操作,但是这样是没办法把默认的发送错误的对话框去掉的。

然后又有人说是不是采用了类似钩子的方法把这个东西在哪里勾掉了。

最后网上查了一番,发现SetUnhandledExceptionFilter这个函数解决了一切。

总结了下搜到的资料,这个函数的返回值有三种情况:

EXCEPTION_EXECUTE_HANDLER equ 1 表示我已经处理了异常,可以优雅地结束了  
EXCEPTION_CONTINUE_SEARCH equ 0 表示我不处理,其他人来吧,于是windows调用默认的处理程序显示一个错误框,并结束  
EXCEPTION_CONTINUE_EXECUTION equ -1 表示错误已经被修复,请从异常发生处继续执行 

具体使用方法如下:

#include   <windows.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[])   
  {   
  SetUnhandledExceptionFilter(callback);   
  _asm   int   3   //只是为了让程序崩溃
  return   0;   
  }

3.实践使用

使用环境 VS2015 QT5.51  客户端程序

LONG WINAPI catchExceptionFileter(_EXCEPTION_POINTERS* pExceptionInfo)
{
    //获取pExceptionInfo中的异常信息,详情查阅_EXCEPTION_POINTERS定义
    //其它自定义处理(弹窗,打报告,日志等)
}

int main(int argc,char *argv[])
{
    //程序其他操作
    //异常检测获取
 LPTOP_LEVEL_EXCEPTION_FILTERpException=SetUnhandledExceptionFilter(catchExceptionFileter);
 _asm   int   3   //只是为了让程序崩溃
}

以上是关于程序崩溃优雅退出之-SetUnhandledExceptionFilter的主要内容,如果未能解决你的问题,请参考以下文章

TestFlight 崩溃报告

『神器点滴之ssh』如何优雅的退出ssh

使用SetUnhandledExceptionFilter让程序优雅的崩溃

26. 后台程序如何优雅的退出

捕获Ctrl + C中断 优雅的退出程序 golang

如何优雅地退出以 twistd 开头的应用程序?