捕获异常时将有用数据转储到控制台

Posted

技术标签:

【中文标题】捕获异常时将有用数据转储到控制台【英文标题】:Dumping Useful Data to Console on Caught Exception 【发布时间】:2010-11-09 22:41:11 【问题描述】:

我有一个CExceptionHandler 类,只要我的应用程序检测到运行时异常,就会调用它。例如:

if ( val == NULL )

    TRACE(_T("Unexpected NULL in sequence."));
    AfxThrowException( ERROR_INVALID_DATA );

AfxThrowException很简单:

void AfxThrowException( DWORD error )

    CExceptionHandler * pException = NULL;

    if ( error == 0 )
    
        error = ::GetLastError();
    

    pException = new CExceptionHandler( error );

    TRACE(_T("Warning: throwing CSerialException for error %d\n"), error);
    THROW(pException);

这是CExceptionHandler的成员Dump函数:

void CExceptionHandler::Dump( CDumpContext & dc ) const

    CObject::Dump(dc);

    dc << "m_dwError = " << m_dwError;

在我的代码中,我有 try/catch 语句:

try

    /* My app does stuff where the exception is thrown. */

catch( CExceptionHandler * ex )

    afxDump << _T("Dumping exceptional data: ") << _T("\r\n");
    ex->Dump( afxDump );
    afxDump << _T("\r\n");

我希望将收集到的调试信息转储到控制台。但是,当 PC 进入 catch 语句(使用断点验证)时,控制台上没有任何反应。我在调试模式下使用 Visual Studio 2008。想法受到赞赏。谢谢。

【问题讨论】:

您是否会抛出动态分配的内存? (泄漏。) @GMan:有没有你使用“原因”而不是“结果”的结果? :)(哦,我认为这对你来说是 MFC。但我对此事的看法只是传闻......) 控制台?这不是MFC吗?试试输出窗口。 @Hans Passant:CExceptionHandler 是 MFC (.dll),但应用程序 (.exe) 不是(Win32 控制台项目)。 嗨,吉姆,我已经根据您的评论更新了我的答案。 【参考方案1】:

CDumpContext 将输出发送到调试器,而不是控制台(有关详细信息,请参阅OutputDebugString),如果您在 Visual Studio 调试器下运行,输出将出现在 Output窗口。

如果您还想将输出发送到控制台,您可以通过在CDumpContext constructor 中传递指向CFile 对象的指针,将CDumpContext 配置为写入CFile

如果您的应用程序是使用“使用多字节字符集”配置选项构建的,您可以使用 CStdioFile 写入 stdout 或 stderr:

CStdioFile file(stdout);
CDumpContext dumpContext(&file);
ex->Dump(dumpContext);

或者,如果你想使用afxDump,你可以直接设置它的m_pFile成员变量(它被声明为public)。例如,您可以将此代码放入您的 main 函数中:

CStdioFile file(stdout);
afxDump.m_pFile = &file;    

但是,如果您的应用程序构建为 Unicode,这将不起作用,因为字符串需要转换为多字节才能写入标准输出。要进行转换,请编写一个继承 CFile 的类:

class CDumpFile : public CFile

    public:
        virtual void Write(const void* lpBuf, UINT nCount);
;

void CDumpFile::Write(const void* lpBuf, UINT nCount)

    // Construct string from array of wide chars
    const wchar_t* p = static_cast<const wchar_t*>(lpBuf);
    UINT len = nCount / sizeof(wchar_t);
    CStringW str(p, len);

    CStringA astr(str); // Convert wide char to multibyte

    fputs((LPCSTR)astr, stdout); // Write multibyte string to stdout

并像这样使用它:

CDumpFile file;
afxDump.m_pFile = &file;

关于您的代码的其他几点:

    您应该确保在catch 块中删除异常对象。如果您的CExceptionHandler 类继承了MFC 的CException,那么您应该调用ex-&gt;Delete()。如果没有,您需要delete ex

    我建议不要将 Afx 前缀用于自己的函数 - 在我看来,您应该考虑将其保留给 MFC 库使用。

我希望这会有所帮助!

【讨论】:

谢谢!我使用CDumpContext dumpContext(&amp;file) 实现了该解决方案,并且它在大多数情况下都有效。但是,它会隔开字符(a C E x c e p t i o n H a n d l e r a t $ 0 0 E 2 4 E 4 0 m _ d w E r r o r = 1 7 0 。对导致此问题的原因有什么想法吗? 是的,这是因为 CStdioFile 正在将 wchar_t 字符串写入控制台,这需要 MBCS。请参阅我的更新答案。

以上是关于捕获异常时将有用数据转储到控制台的主要内容,如果未能解决你的问题,请参考以下文章

如何获取已处理异常的故障转储?

前端捕获异常技巧总结

在核心数据更改处理期间捕获到异常

未捕获异常的角度中断/暂停

Thread如何捕获异常

Thread如何捕获异常