我在main函数的堆栈中有一些对象:
int main(...)
{
CFoo foo;
CBar bar;
}
另外,我有一个函数,可以跟踪我的应用程序中的错误:
void Err(std::string msg)
{
SomehowLogErrorMessage(msg);
exit(1);
}
当我必须报告致命错误时,Err函数绝对有用。我只是记录错误并终止应用程序 - 在发生此类错误后无法恢复。但是,以“exit()”结尾不会调用foo和bar析构函数 - 这是我实际预期的行为(但是错误)。 “abort()”也无济于事。另外,我不能使用异常来在main()中捕获它们。有没有其他方法来实现Err函数,它终止应用程序并正确清理堆栈对象?或者我应该以某种方式重新设计我的错误处理?
谢谢!
P.S。顺便说一句,我不能将WM_QUIT消息发送到我的主窗口?我对WinAPI并不擅长,但我的应用程序是纯Win32,而我的Err()函数可以获得我的主窗口的句柄。它会起作用吗?
答案 0 :(得分:3)
并非没有异常或正常从Err返回,一直到callstack。你需要解开堆栈。
答案 1 :(得分:2)
还有C setjmp
和longjmp
。它应该返回main
,因此程序将在离开main
的范围后照常终止,在这种情况下,C ++的析构函数机制将在main
中销毁您的本地对象。
当然,在C ++中使用longjmp
是有道理的。它将跳过堆栈上的任何其他函数,因此它仅适用于main
中的几个堆栈对象。
在堆上分配对象并在delete
中手动Err
可能更容易。
答案 2 :(得分:1)
基本上有两种方法可以在C ++中传播错误:异常(你似乎被任意排除)和返回代码。
由于您无法使用异常,因此您需要开始从可能失败的函数中传递返回代码并测试它们以查看是否需要停止并返回到main。如果你不像这样展开堆栈,就无法保证将正确调用析构函数。
还要考虑如果你的程序处于致命状态,那么析构函数是否能够实际清理?如果对象状态有缺陷且无法正常取下怎么办?而不是调用exit,你可以调用abort
,如果你进入一个糟糕的状态,它至少会留下一个核心来帮助诊断问题。对于没有例外情况的致命错误,这是一个合理的选择。
答案 3 :(得分:0)
我相信Exit
会立即终止申请。要查看您期望foo
和bar
的行为,必须超出范围。这意味着主函数必须通常以返回值结束。而不是从你的Err函数调用Exit()
,你需要找到一种方法来返回你的main函数,让它正常返回错误值。
答案 4 :(得分:0)
我会重新设计你的错误处理。最直接的做法是将控制权返回到main
,然后让它进行正常清理。异常通过堆栈展开提供此功能,但您不能使用异常。好没关系。有时你不能使用例外。
因此,不要让Err
尝试关闭程序,而是让Err
记录错误并返回错误代码。理想情况下,Err
无论如何都不应该做两个工作,你试图让它做:1)记录错误,2)优雅地终止应用程序。
如果您的应用程序碰巧是多线程的,那么您可能会很容易出错。在错误记录线程中,发出“die”事件的信号。让主线程等待此事件以及它等待的任何其他内容(或通过QueueUserAPC
或类似方式向其注入作业)。发出事件信号后,请关闭应用程序。