【问题标题】: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 控制台项目)。
  • 嗨,吉姆,我已经根据您的评论更新了我的答案。

标签: c++ visual-studio-2008 mfc exception-handling console-application


【解决方案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;

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

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

  2. 我建议不要将 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。请参阅我的更新答案。
猜你喜欢
  • 2019-04-09
  • 2013-07-13
  • 1970-01-01
  • 2018-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-08
  • 2011-02-23
相关资源
最近更新 更多