谢谢。
欢迎提供代码。
1. Win32
Win32 API包含一种通过SetUnhandledExceptionFilter函数来实现此功能的方法,具体如下:
LONG myFunc(LPEXCEPTION_POINTERS p)
{
printf("Exception!!!\n");
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)&myFunc);
// generate an exception !
int x = 0;
int y = 1/x;
return 0;
}
2. POSIX/Linux
通常我会通过signal()函数来处理SIGSEGV信号。你也可以处理SIGTERM信号和SIGINT信号,但不能处理SIGKILL信号(这是设计如此)。你可以使用strace()来获取回溯信息以查看信号的原因。
有sysinternals论坛帖子讨论如何通过挂钩NT内部来防止终止进程的尝试,但你真正需要的是看门狗或同级进程(合理的方法),或者拦截灾难性事件的一些方法(相当冒险)。
编辑:他们有很多原因让这个过程变得困难,但是拦截或阻止杀死进程的尝试是可能的。我知道你只是想在退出之前清理一下,但是一旦有人释放了一个无法立即终止的进程,就会有人要求立即终止它的方法,依此类推。总之,如果要走这条路,请参见上面链接的线程,并搜索其中的一些关键词以获取更多信息,例如hook OR filter NtTerminateProcess等。我们在这里谈论内核代码、设备驱动程序、反病毒软件、安全、恶意软件、rootkit等内容。在这个领域帮助你的一些书籍是Windows NT/2000 Native API,Undocumented Windows 2000 Secrets: A Programmer's Cookbook,Rootkits: Subverting the Windows Kernel,当然还有Windows® Internals: Fifth Edition。这些东西编码不太难,但是非常敏感,你可能会引入意外的副作用。
也许 应用程序恢复和重启功能 可以派上用场?支持 Vista 和 Server 2008 及以上版本。
ApplicationRecoveryCallback 回调函数 应用程序定义的回调函数,用于在应用程序遇到未处理的异常或变得无响应时保存数据和应用程序状态信息。
在使用 SetUnhandledExceptionFilter 时,MSDN Social 讨论 建议为了可靠地使其工作,唯一的方法是在内存中打补丁来确保您的过滤器得到调用。建议改用 __try/__except 进行封装。无论如何,在文章 "SetUnhandledExceptionFilter" and VC8 中有关于过滤对 SetUnhandledExceptionFilter 的调用的示例代码和讨论。
此外,请参阅The Awesome Factor的Windows SEH Revisited,其中包含一些使用AddVectoredExceptionHandler的示例代码。取决于你如何处理异常。如果你正确地处理并退出程序,你可以使用 atexit()
注册你的函数以在退出时调用。
在真正的异常终止(如段错误)的情况下,它不起作用。
我不知道 Windows 是否支持,但在符合 POSIX 标准的操作系统上,您可以安装信号处理器来捕获不同的信号并对其进行处理。当然,你无法捕获 SIGKILL
和 SIGSTOP
信号。
信号 API 是自 C89 以来 ANSI C 的一部分,所以很可能 Windows 支持它。有关详细信息,请查看 signal()
系统调用。
如果只在Windows上运行,那么可以使用SEH(SetUnhandledExceptionFilter),或者VEH(AddVectoredExceptionHandler,但仅适用于XP/2003及以上版本)
抱歉,我不是Windows程序员。但也许
_onexit()
注册一个函数,以便在程序终止时被调用。
http://msdn.microsoft.com/en-us/library/aa298513%28VS.60%29.aspx
首先,尽管这很明显:你永远无法拥有完全健壮的解决方案 - 某人总是可以只需击中电源电缆来终止您的进程。因此,您需要达成妥协,并仔细制定妥协的细节。
其中一个更健壮的解决方案是将相关代码放入包装程序中。包装程序调用您的“真实”程序,等待其进程终止,然后 - 除非您的“真实”程序特别发出已正常完成的信号 - 运行清理代码。这在诸如测试套件之类的东西中非常常见,测试程序可能会以意外的方式崩溃、中止或其他死亡。
这仍然会给您带来困难,即如果某人对您的包装函数执行 TerminateProcess,那么该怎么办。如果必要,您可以将其设置为 Windows 中的服务,并使用操作系统的功能在其死亡时重新启动它。(这只是稍微改变了一些事情;某人仍然可以停止服务。)此时,您可能已经到达需要通过创建文件等持久性信号来标志成功完成的阶段。