MessageBox“异常程序终止”使我的应用程序保持运行

时间:2014-08-14 10:19:10

标签: c++ c windows abort c++builder-6

......有点儿。正如这个极其简单的例子所示,

enter image description here

很少(到目前为止只报告过一次),我的应用程序之一就会崩溃。我想像通常那样在发生非特定异常时终止它。我的策略是(低级别)记录问题,然后终止。该应用程序是子系统的一部分,如果检测到任何问题,我想(重新)启动它。它是用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)可靠吗? ......或者至少可以建立一些东西?

4 个答案:

答案 0 :(得分:4)

在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;
}

答案 1 :(得分:1)

当未处理的异常导致终止时,您可以使用Windows错误报告来创建进程的转储。然后,您可以在闲暇时查看转储,并允许某些父进程或其他监视程序重新启动您的进程。如果您选择此策略,则会尝试处理代码中的失败,但允许它。

答案 2 :(得分:1)

如果要捕获任何程序退出,请查看atexit()。如果您想捕获所有终止事件,请查看std::set_terminate(),如果您想要捕获所有意外异常,请查看std::set_unexpected()。如果您只想捕获abort(),可以使用SIGABRT 信号值来呼叫signal()。您还可以使用try{your code}catch(...){custom event handler}包装代码。

答案 3 :(得分:1)

我可以做一些测试,我只能确认注册一个SIGABRT信号处理程序只是一个NOOP。

我尝试使用VS2008 Express编写的非常简单的GUI应用程序。 :

  • 没有框架,也没有.NET,只有Win API
  • 一个带退出和致命的菜单
  • 菜单直接在WndProc中管理
  • 致命执行1/0

结果如下:

  • 没有特别的行动=> Windows打开一个消息框,指示致命错误......
  • SIGABRT的信号处理程序=>相同的MessageBox
  • C ++ try catch(...)=>相同的MessageBox
  • WndProc中的SEH:可以拦截错误!
  • SEH围绕消息循环:可以拦截错误!

如果我放置机器人SEH处理程序,最内部(WndProc)捕获。

对您而言,新的好处是,如果足够来保护消息循环,并且您不必进入每个WndProc。

糟糕的是,我不了解C ++构建器,也无法说明在哪里找到消息循环。

为了给你一个线索,这是我如何保护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 ++构建器在其消息循环中已经有这样的异常处理程序。

希望它有所帮助...