在异常处理程序内部,MessageBox()成功返回IDOK但从未显示

时间:2012-11-05 01:28:36

标签: c++ windows winapi exception-handling

我正在使用一个名为windows_error的自编写异常类,它继承自std :: runtime_error,我用它来正确处理来自Windows API函数的意外错误。

一直到callstack的底部,在我的WinMain函数的末尾,我捕获了尚未处理的所有windows_error异常。我打算通过在程序终止之前显示错误消息来处理它们,如下所示:

int WINAPI wWinMain(HINSTANCE inst, HINSTANCE prev, wchar_t *cmdline, int winshow)
{
    // Initialize result to EXIT_FAILURE in case the program terminates due to
    // an exception.
    int result = EXIT_FAILURE;

    try {
        result = sIRC()();
    }
    catch (windows_error &e) {
        e.basicHandler();
    }

    return result;
}

basicHandler成员函数如下所示:

void windows_error::basicHandler() const
{
    std::wostringstream ss;

    ss << L"An unexpected error has occurred in a Windows function.\n\n" \
          L"Function " << m_api << L" was called by " << m_caller << L" in " << m_srcFile << L" at line " << m_srcLine << L". " \
          L"It returned error " << m_error << L":\n\n" << m_errorMessage;

#ifdef _CONSOLE
    std::wcout << L"\n" << ss.str();
#else
    auto result = MessageBox(HWND_DESKTOP, ss.str().c_str(), L"Windows error!", MB_ICONERROR);
    result = result; // I added this line so I can put a breakpoint in the debugger
#endif // _CONSOLE
}

当我开始使用我正在进行的程序时,这种方法非常有效。但现在该计划正在开始增长。在尝试新代码时,我注意到该程序似乎意外终止。通过在Visual C ++ 2010调试器中运行它,我注意到抛出了一个windows_error异常。通过逐步执行basicHandler函数,我可以看到MessageBox函数返回1(IDOK)而没有实际显示消息框...

什么可能导致这种行为?

我知道我的描述有点模糊,但我不知道还有什么要添加...我在MSDN上找不到任何暗示这种行为甚至可能的内容。我没有传递给MessageBox的父窗口句柄,因为它们在堆栈展开期间都被销毁了。我也很肯定堆栈没有通过窗口过程或任何其他Windows回调解除。

任何暗示都会受到赞赏。

1 个答案:

答案 0 :(得分:0)

雷蒙德在我对我的问题的评论中提供了我需要的暗示。在堆栈展开期间,我的user_interface类的析构函数在窗口句柄上调用DestroyWindow,因为它在该点仍然有效。我不知道的是MessageBox解释生成的WM_QUIT消息以关闭它自己。我以为消息框有自己的内部消息队列?

我能够通过修改user_interface类的析构函数来解决我的问题。

是:

if (_wnd)
    DestroyWindow(_wnd);

我把它改为:

if (_wnd) {
    DestroyWindow(_wnd);

    MSG msg = MSG();
    while (msg.message != WM_QUIT) {
        GetMessage(&msg, 0, 0, 0);
    }
}

这有效,但看起来有点难看。有什么建议可以改善这个吗?