7

我正在将 Visual C++ 应用程序移植到 GCC(应该建立在 MingW 和 Linux 上)。

现有代码__try { ... } __except(1) { ... }在一些地方使用块,因此几乎没有什么(可能是内存不足类型错误?)会使程序退出而不做一些最小的日志记录。

用 GCC 做类似的事情有哪些选择?

编辑:感谢 Visual Studio 中指向 /EH 选项的指针,我现在需要一些关于如何在 Linux 上处理信号的示例。我从 2002 年发现了这条消息。

除了我应该注意的其他信号SIGFPESIGSEVG?(主要关心那些可能从做错事中提出的问题)

赏金信息:我希望我的应用程序能够在退出之前自行记录尽可能多的错误情况。

我可能会收到哪些信号,哪些信号通常不可能在之后记录错误消息?(内存不足,还有什么?)

我如何以一种可移植的方式处理异常和(最重要的)信号,使代码至少在 Linux 和 MingW 上运行相同。#ifdef 没问题。

我不只是有一个记录失败的包装进程的原因是,出于性能原因,我保存将一些数据写入磁盘直到最后一分钟,所以如果出现问题,我想尽一切可能尝试在之前写出数据退出。

4

5 回答 5

12

try { xxx } catch(...) { xxx } 会更便携,但可能不会捕获那么多。这取决于编译器设置和环境。

使用默认的 VC++ 设置,异步 (SEH) 错误不会传递到 C++ EH 基础架构;要捕获它们,您需要改用 SEH 处理程序 (__try/__except)。VC++ 允许您通过 C++ 错误处理来路由 SEH 错误,这允许 catch(...) 捕获 SEH 错误;这包括内存错误,例如空指针取消引用。 详情

然而,在 Linux 上,Windows 使用 SEH 处理的许多错误都是通过信号指示的。这些永远不会被 try/catch 捕获;要处理它们,您需要一个信号处理程序。

于 2008-09-02T11:11:01.103 回答
0

为什么不使用 C++ 标准异常而不是 MSFT 的专有扩展?C++ 有一个异常处理的概念。

struct my_exception_type : public logic_error {
    my_exception_type(char const* msg) : logic_error(msg) { }
};

try {
    throw my_exception_type("An error occurred");
} catch (my_exception_type& ex) {
    cerr << ex.what << endl;
}

C++ 也有一个“catchall”子句,所以如果你想记录异常,你可以使用下面的包装器:

try {
    // …
}
catch (...) {
}

但是,这在 C++ 中效率不高,因为创建这样一个通用包装器意味着编译器必须将处理代码插入到每个后续堆栈帧中(不像在 .NET 等托管系统中,只要只要实际上没有抛出异常)。

于 2008-09-02T11:07:37.913 回答
0

对于可移植性,要尝试的一件事是对大多数普通异常使用 try-catch 块,然后设置终止处理程序 (set_terminate_handler) 以具有可用于灾难性退出条件的最小挂钩。您还可以尝试添加类似 atexit 或 on_exit 处理程序的内容。当然,当您输入这些函数时,您的执行环境可能会很奇怪或损坏,因此请注意您认为环境正常的程度。

最后,当使用常规的 try-catch 对时,您可以考虑使用函数 try 块,而不是在函数体中打开 try 块:

int foo(int x) try {
  // body of foo
} catch (...) {
   // be careful what's done here!
}

它们是相对未知的 C++ 块,在某些情况下,即使在部分(小规模)堆栈损坏的情况下也可能提供恢复。

最后,是的,您可能需要调查哪些信号可以自己持续处理或哪些信号可能会中止,如果您想要较少的处理机制,您可以考虑调用新操作符的无抛出版本, 并在需要时编译为不生成浮点异常(您始终可以检查 isnan(.)、isfinite(.)、FP 结果以保护自己)。

最后一点,请注意:我注意到浮点结果分类函数可以在 linux 和 windows 下的不同标题中......所以你可能必须对这些包含进行条件化。

如果您觉得很顽皮,请使用 setjmp 和 longjmp 全部编写(这是个笑话……)。

于 2008-09-05T22:01:43.650 回答
0

捕捉 C++ 异常catch(...)已经让你陷入了迷茫。

试图捕捉未被捕捉到的错误catch(...)会让你完全陷入未定义的行为。没有 C++ 代码可以保证工作。您的最小日志代码可能会导致导弹发射。

我的建议是不要尝试catch(...)。仅捕获您可以有意义且安全地记录的异常,并让操作系统处理其余的(如果有)。

如果在根本原因之上还有错误处理代码故障,那么事后调试会变得很糟糕。

于 2009-07-24T18:34:39.627 回答
-1

一种易于使用、可移植且几乎不使用任何资源的方法是捕获空类。我知道这起初可能听起来很奇怪,但它可能非常有用。

这是我为另一个问题制作的示例,也适用于您的问题:link

此外,您可以有超过 1 个捕获:

try
{
   /* code that may throw exceptions */
}
catch (Error1 e1)
{
   /* code if Error1 is thrown */
}
catch (Error2 e2)
{
   /* code if Error2 is thrown */
}
catch (...)
{
   /* any exception that was not expected will be caught here */
}
于 2009-07-23T17:58:00.290 回答