MessageBox“程序异常终止”让我的应用程序继续运行
Posted
技术标签:
【中文标题】MessageBox“程序异常终止”让我的应用程序继续运行【英文标题】:MessageBox "Abnormal program termination" keeps my application running 【发布时间】:2014-10-07 23:07:18 【问题描述】:...有点。正如这个极其简单的例子所示,
非常罕见(到目前为止仅报告过一次),我的一个应用程序碰巧以这种方式崩溃。当发生非特定异常时,我想像往常一样终止它。我的策略是(低级)记录问题,然后终止。该应用程序是子系统的一部分,如果检测到任何问题,我想(重新)启动它。它使用 C++-Builder 6 构建并在 Windows (XP...7, 也是 8) 上运行。我了解到abort()
很可能导致了错误消息。该应用程序有一个 GUI,这就是为什么会显示一个消息框而不是仅仅向stderr
进行(解除阻塞)输出。
只要消息框不被用户接受,我的应用程序明显保持运行,例如它处理计时器(上面示例中的生命周期增加)或进程间消息,完全不知道这个问题。
在阅读了What is the easiest way to make a C++ program crash?和Difference between raise(SIGABRT) and abort() methods的一些答案后,我尝试了以下
void mySignalHandler(int sig)
// low-level error reporting here
exit(-1);
void __fastcall TForm1::FormCreate(TObject *Sender)
signal(SIGABRT, mySignalHandler);
// some more initialisation here
如果abort()
或raise(SIGABRT)
被调用,它也可以让我的应用程序终止。 (我也希望阻止Windows“寻找问题的解决方案”。)
从您的角度来看,这(为 abort 注册一个信号处理程序并在那里调用 exit)可靠吗? ...或者至少可以建立一些东西?
【问题讨论】:
为什么不简单地尝试调试程序以找出崩溃的原因?如果你修复了崩溃,它们就不会再发生了。 使用 POSIX 信号 api 来捕获 Windows 问题并不能很好地工作。使用 SEH。 @JoachimPileborg 这并不简单,但我这样做了。同时系统无论如何都要运行...... @bmargulies 一个用户报告了这个消息框(直到今天才一次),我的应用程序没有使用 POSIX 信号,它一定是由某些库引起的。 “只要消息框不被用户接受,我的应用程序显然会继续运行,”- wat 【参考方案1】:在 C++Builder 安装文件夹中,检查以下文件:
source\cpprtl\Source\misc\errormsg.c -_ErrorMessage
的实现
source\cpprtl\Source\procses\abort.c - 实现abort
,它调用_ErrorMessage
source\cpprtl\Source\misc\assert.c - 实现_assert
,它调用_ErrorMessage
errormsg.c 定义了一个未记录的_messagefunc
函数指针,您可以将其设置为覆盖默认行为。尽管它没有记录,也没有在任何头文件中声明,但您可以将其声明为 extern
并以这种方式访问它。示例用法:
extern int (_RTLENTRY * _EXPDATA _messagefunc)(char *msg);
static int LogAndDie(char *msg)
LogMessageToSomeFile(msg);
exit(1);
return 0;
void InitializeErrorHandling()
_messagefunc = LogAndDie;
【讨论】:
我认为您的建议需要重新考虑。_messagefunc
指向的函数应该只处理错误消息,即记录它。被_ErrorMessage
间接调用,这个函数也用在非致命的情况下。
@Wolf - 嗯。几年来,我们一直在生产环境中使用 _messagefunc
运行代码(不是按照您的意愿终止,而是使用 _messagefunc
将错误转化为问题跟踪器的问题报告)。我在实践中看到的唯一非致命错误是数学错误(例如取log(0)
),这对于您的应用程序域可能不是问题。无论如何,检查strcmp(msg, "Abnormal program termination") == 0
应该足以只得到致命错误。
建议的解决方案没有帮助,但研究的建议有帮助。它帮助我更好地了解发生了什么。所以我接受这是迄今为止最好的最有帮助的答案。【参考方案2】:
当未处理的异常导致终止时,您可以使用 Windows 错误报告创建进程转储。然后,您可以在闲暇时查看转储,并允许某些父进程或其他看门狗重新启动您的进程。如果您选择此策略,您将不会尝试处理代码中的故障,而是允许它。
【讨论】:
除了 Windows 错误报告的想法(我还有待探索):我不认为在这种情况下存在飞行异常。【参考方案3】:如果您想捕获任何程序退出,您应该查看atexit()。如果您想捕获所有终止事件,请查看std::set_terminate(),如果您想捕获所有意外异常,请查看std::set_unexpected()。如果您只想捕获abort()
,您可以使用SIGABRT
信号值 调用signal()。您还可以使用tryyour codecatch(...)custom event handler
包装您的代码。
【讨论】:
也许我对此不够清楚:异常真的不是我的问题,而是没有异常。If you want to capture only abort() you can call signal() with the SIGABRT signal value.
这正是我所做的。毫无疑问,这在技术上是可行的。 (您的答案中的所有其他信息都与我的问题无关,所以,对不起,-1)相反,我想知道,在调用此函数时如何正确退出我的程序。我会尝试将此详细信息添加到问题中。
@Wolf 我的回答是在您第一次在这里提出问题时理解您的问题 - 从那时起您已经对原始问题进行了 6 次编辑。您自己在上面承认,您可能不够清楚。
我觉得您的回答与问题的第一个版本不匹配 ***.com/posts/25305653/timeline 我在第一条评论中说过。关于可能的编程错误,您的回答非常普遍(例如,将其与this answer 进行比较)。你不认为你可以更具体吗?
@Wolf 如果您的问题一开始就很清楚,那么为什么之后需要对您的问题进行六次编辑?当问题出在你自己写得不好的问题上时,也许你不应该投票给别人。【参考方案4】:
我可以做一些测试,我只能确认注册 SIGABRT 信号处理程序只是一个 NOOP。
我尝试了一个用 VS2008 Express 编写的非常简单的 GUI 应用程序。 :
没有框架,也没有 .NET,只有 Win API 一个带有退出和致命的菜单 直接在 WndProc 中管理的菜单 致命执行 1/0结果如下:
没有特殊操作 => windows 打开一个 MessageBox 指示致命错误... SIGABRT 的信号处理程序 => 相同的 MessageBox C++ 尝试 catch(...) => 相同的消息框 WndProc 中的 SEH:可以拦截错误! 消息循环周围的 SEH:可以拦截错误!如果我放置机器人 SEH 处理程序,最内部 (WndProc) 会捕获。
对您来说,好消息是 if 足够 来保护消息循环,并且您不必进入每个 WndProc。
坏消息是我不知道 C++ builder,也不能说在哪里可以找到消息循环。
只是给你一个线索,下面是我如何保护 WinAPI 应用程序中的消息循环:
__try
while (GetMessage(&msg, NULL, 0, 0))
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
TranslateMessage(&msg);
DispatchMessage(&msg);
__except (EXCEPTION_EXECUTE_HANDLER)
::MessageBox(NULL, _T("FATAL"), _T("MAIN"), MB_OK | MB_ICONERROR);
这样,我可以看到我自己的消息框,但没有其他内容,如果我评论我的消息框,应用程序会静默退出。
但是...由于您显示的消息不是原始的 Windows 消息,我怀疑 C++ 构建器在其消息循环中已经有这样一个异常处理程序。
希望对你有帮助...
【讨论】:
感谢您的研究! C++-Builder(6) GUI 应用程序基于 VCL 框架。消息循环由Application::Run
运行,不受应用程序源的直接影响。我希望更好地遵守这个约定。
我曾经(很久很久以前)使用过 BC 编译器,如果我没记错的话,主应用程序类扩展了 Application,并且可以覆盖很多东西(包括 run 或 .. 。环形)。还可以吗?
这是在很早的TVision 时代,它在 Windows 下发生了变化,因为 Windows 本身是基于自己的事件控制的 GUI 概念。
不太老,Windows 3.11 时代,但它仍然在我的记忆中很远......由于 VCL 不公开可用,我只能建议你照顾所有可覆盖的方法...... 以上是关于MessageBox“程序异常终止”让我的应用程序继续运行的主要内容,如果未能解决你的问题,请参考以下文章
MessageBox.Show不适用于我的Visual Studio
即使在异常终止时,如何确保调用 UnhookWindowsHookEx?