【问题标题】:Using std::runtime_error instead of CException使用 std::runtime_error 而不是 CException
【发布时间】:2011-07-15 23:50:35
【问题描述】:

当我在主线程中抛出一个 CException 时,它会被框架巧妙地捕获,并且一个漂亮的 MessageBox 会显示错误文本。当我抛出 std::runtime_error 时,应用程序就会崩溃。问题是我没有看到异常的文本,我必须花时间弄清楚它实际上是我“抛出”的东西,而不是简单的访问冲突。

所以我想知道是否有办法让 std::exception 被捕获并以与 CException 类似的方式显示其文本。

我希望能够从任何消息处理程序中抛出 std::runtime_error 而不会导致我的程序崩溃,也不需要将每个消息处理程序包装在 try...catch 中。这对于 CException 来说已经成为可能,因为在事件泵的代码中某处有一个 try...catch(我认为它是 CWinApp::Run - 但我不确定)。

[编辑] 我找到了捕获 CExceptions 的函数,但我不确定是否可以覆盖它。我已经发布了下面的代码。 TRY...CATCH_ALL...END_CATCH_ALL 语句正在捕获 CExceptions。

/////////////////////////////////////////////////////////////////////////////
// Official way to send message to a CWnd

LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,
    WPARAM wParam = 0, LPARAM lParam = 0)
{
    _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
    MSG oldState = pThreadState->m_lastSentMsg;   // save for nesting
    pThreadState->m_lastSentMsg.hwnd = hWnd;
    pThreadState->m_lastSentMsg.message = nMsg;
    pThreadState->m_lastSentMsg.wParam = wParam;
    pThreadState->m_lastSentMsg.lParam = lParam;

#ifdef _DEBUG
    _AfxTraceMsg(_T("WndProc"), &pThreadState->m_lastSentMsg);
#endif

    // Catch exceptions thrown outside the scope of a callback
    // in debug builds and warn the user.
    LRESULT lResult;
    TRY
    {
#ifndef _AFX_NO_OCC_SUPPORT
        // special case for WM_DESTROY
        if ((nMsg == WM_DESTROY) && (pWnd->m_pCtrlCont != NULL))
            pWnd->m_pCtrlCont->OnUIActivate(NULL);              
#endif

        // special case for WM_INITDIALOG
        CRect rectOld;
        DWORD dwStyle = 0;
        if (nMsg == WM_INITDIALOG)
            _AfxPreInitDialog(pWnd, &rectOld, &dwStyle);

        // delegate to object's WindowProc
        lResult = pWnd->WindowProc(nMsg, wParam, lParam);

        // more special case for WM_INITDIALOG
        if (nMsg == WM_INITDIALOG)
            _AfxPostInitDialog(pWnd, rectOld, dwStyle);
    }
    CATCH_ALL(e)
    {
        lResult = AfxProcessWndProcException(e, &pThreadState->m_lastSentMsg);
        TRACE(traceAppMsg, 0, "Warning: Uncaught exception in WindowProc (returning %ld).\n",
            lResult);
        DELETE_EXCEPTION(e);
    }
    END_CATCH_ALL

    pThreadState->m_lastSentMsg = oldState;
    return lResult;
}

【问题讨论】:

    标签: c++ exception mfc


    【解决方案1】:

    所以我想知道是否有办法 捕获 std::exception 及其 文本以类似的方式显示 异常。

    是的 - 通过捕捉它,并通过 MessageBox 显示它的文本。

    int main() {
        try {
            //....
        }
        catch(const std::exception& except) {
            MessageBox(NULL, except.what(), "OMGWTF FATAL ERROR", MB_OK);
        }
    }
    

    【讨论】:

    • +1 表示“OMGWTF 致命错误”;)。但你真的应该把它当作const&
    • 并且 MessageBox 的参数顺序错误。见博的回答。
    【解决方案2】:

    有,但你必须自己做。 :-)

    int main()
    {
        try
        {
            SomeFunction();
        }
        catch (const std::exception & ex)
        {
            ::MessageBox(0, ex.what(), 0, 0);
        }
    }
    

    【讨论】:

      【解决方案3】:

      在 MFC 的主消息循环实现中的某个地方,它有一个 try/catch 设置,当CException 类型被抛出时,它会给出你看到的行为。

      您可以将自己的代码包装在各种 try/catch 语句中以捕获异常,正如其他人已经说过的那样。

      还可以使用一种“顶级”处理程序来包装 MFC 的消息循环,以捕获任何其他方式未捕获的内容。为此,请在派生的应用程序类中覆盖 CWinApp::Run,实现所需的 try/catch,然后在 try 块中调用基类 CWinApp::Run

      int CMyApp::Run()
      {
          try
          {
              return CWinApp::Run();
          }
          catch(const std::exception& ex)
          {
              MessageBox(NULL, ex.what(), "Error", MB_OK | MB_ICONERROR);
              return 1;  // or some appropriate code
          }
      }
      

      【讨论】:

      • 谢谢,我找到了哪个函数捕获了 CExceptions(它是 AfxCallWndProc),并且我已经编辑了我的问题。但我不确定是否可以覆盖它,因为它不是真正的虚函数。 CWinApp::Run 确实调用了它,但它在调用堆栈中就像它上面的 20-30 个条目。
      【解决方案4】:

      如果您有可以合理地继续处理的异常,您也可以覆盖 CWinApp::PumpMessage() 来替代 CWinApp::Run() 或除 CWinApp::Run() 之外。

      【讨论】:

        猜你喜欢
        • 2010-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-20
        • 1970-01-01
        • 1970-01-01
        • 2011-04-16
        • 1970-01-01
        相关资源
        最近更新 更多