6

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

在此处输入图像描述

很少(到目前为止仅报告一次),我的一个应用程序以这种方式崩溃。当发生非特定异常时,我想像往常一样终止它。我的策略是(低级)记录问题,然后终止。该应用程序是子系统的一部分,如果检测到任何问题,我想(重新)启动它。它使用 C++-Builder 6 构建并在 Windows (XP...7, 也是 8) 上运行。我了解到abort()最有可能导致错误消息。该应用程序有一个 GUI,这就是为什么会显示一个消息框而不是仅仅向stderr.

只要消息框不被用户接受,我的应用程序就会明显地运行,例如它处理计时器(上面示例中的生命周期增加)或进程间消息,完全不知道这个问题。

在阅读了一些答案后,什么是使 C++ 程序崩溃的最简单方法?raise(SIGABRT) 和 abort() 方法之间的区别,我尝试了以下

void mySignalHandler(int sig)
{
    // low-level error reporting here
    exit(-1);
}

void __fastcall TForm1::FormCreate(TObject *Sender)
{
    signal(SIGABRT, mySignalHandler);
    // some more initialisation here
}

如果或被调用,这也可以让我的应用程序正确终止。(我还希望阻止 Windows“寻找问题的解决方案”。)abort()raise(SIGABRT)

从您的角度来看,这(为 abort 注册一个信号处理程序并在那里调用 exit)可靠吗?...或者至少可以建立一些东西?

4

4 回答 4

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函数指针,您可以将其设置为覆盖默认行为。尽管它没有记录并且没有在任何头文件中声明,但您可以将其声明为 anextern并以这种方式访问​​它。示例用法:

extern int (_RTLENTRY * _EXPDATA _messagefunc)(char *msg);

static int LogAndDie(char *msg)
{
  LogMessageToSomeFile(msg);
  exit(1);
  return 0;
}

void InitializeErrorHandling()
{
  _messagefunc = LogAndDie;
}
于 2014-08-14T12:57:38.717 回答
1

当未处理的异常导致终止时,您可以使用 Windows 错误报告创建进程转储。然后,您可以在闲暇时查看转储,并允许某些父进程或其他看门狗重新启动您的进程。如果您选择了这种策略,您将不会尝试处理代码中的故障,而是允许它发生。

于 2014-08-14T10:37:20.553 回答
1

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

于 2014-08-14T11:25:12.543 回答
1

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

我用 VS2008 Express 编写的一个非常简单的 GUI 应用程序进行了尝试。:

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

结果如下:

  • 没有特殊操作 => windows 打开一个 MessageBox 指示致命错误...
  • SIGABRT 的信号处理程序 => 相同的 MessageBox
  • C++ 尝试 catch(...) => 相同的 MessageBox
  • WndProc中的SEH:可以拦截错误!
  • SEH环绕消息循环:可以拦截错误!

如果我放置 bot 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++ 构建器在其消息循环中已经有了这样的异常处理程序。

希望能帮助到你 ...

于 2014-08-14T13:30:43.863 回答