检测程序终止(C,Windows)

我有一个程序必须在完成之前执行某些任务。 问题是,有时程序崩溃,例外(如无法达到数据库等)。 现在,有没有办法检测到一个exception终止,并执行一些代码之前死亡?

谢谢。

代码表示赞赏。

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内部,但你真正想要的是一个监督或同行过程(合理的方法)或拦截灾难性事件(相当危险)的一些方法。

编辑:他们为什么要这么做是有原因的,但是拦截或者阻止企图杀死你的过程是可能的。 我知道在退出之前你只是想清理一下,但是一旦有人释放了一个无法立即杀死的进程,就会有人要求立即杀死它的方法,等等。 无论如何,要走下这条路,看上面的链接,并搜索一些关键字,你在那里找到更多。 挂钩或过滤NtTerminateProcess等。我们在这里谈论内核代码,设备驱动程序,反病毒,安全,恶意软件,rootkit的东西。 在这方面的一些书籍是Windows NT / 2000 Native API , 未记录的Windows 2000的秘密:程序员的食谱 , Rootkits:颠覆Windows内核 ,当然, Windows®内部:第五版 。 这个东西不是很难编码,但是很敏感,只要正确,你可能会引入意想不到的副作用。

也许应用程序恢复和重启功能可能是有用的? Vista和server 2008及以上版本支持。

ApplicationRecoveryCallback回调函数应用程序定义的回调函数,用于在应用程序遇到未处理的异常或无响应的情况下保存数据和应用程序状态信息。

关于使用SetUnhandledExceptionFilter , MSDN社会讨论建议,要使其可靠地工作,修补该方法的内存是唯一的方法来确保您的过滤器被调用。 建议用__try / __来包装除外。 无论如何,在文章“SetUnhandledExceptionFilter”和VC8中有一些示例代码和对SetUnhandledExceptionFilter过滤调用的讨论。

另外,请参阅Awesome Factor中的Windows SEH ,了解AddVectoredExceptionHandler的一些示例代码。

这取决于你如何处理你的“例​​外”。 如果你正确处理它们并退出程序,你可以使用atexit()注册你在退出时调用的函数。

如果发生真正的异常终止,它将不起作用,像段错误。

不知道Windows,但在POSIX兼容的操作系统,你可以安装信号处理程序,将捕获不同的信号,并做一些事情。 当然,你不能赶上SIGKILLSIGSTOP

信号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中将其设置为服务并使用操作系统的功能在死亡时重新启动它来解决此问题。 (这只是改变了一些东西,有人仍然可以停止服务。)在这一点上,你可能正处于一个需要通过诸如创建一个文件之类的持久性来表示成功完成的点。

我在ddj.com发表了一篇关于几年前的“验尸调试”的文章。

它包括Windows和Unix / Linux的来源,以检测异常终止。 根据我的经验,使用SetUnhandledExceptionFilter安装的窗口句柄并不总是被调用。 在许多情况下,它被称为,但我收到了不少来自客户的日志文件,不包括来自已安装的处理程序的报告,即存在违反原因。

http://www.ddj.com/development-tools/185300443