开发者

Dumping Useful Data to Console on Caught Exception

I have a CExceptionHandler class that is invoked whenever my application detects a run-time exception. For example:

if ( val == NULL )
{
    TRACE(_T("Unexpected NULL in sequence."));
    AfxThrowException( ERROR_INVALID_DATA );
}

AfxThrowException is very simple:

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);
}

This is the member Dump function of CExceptionHandler:

void CExceptionHandle开发者_Python百科r::Dump( CDumpContext & dc ) const
{
    CObject::Dump(dc);

    dc << "m_dwError = " << m_dwError;
}

Higher up in my code I have the try/catch statements:

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");
}

I would like the collected debug information to be dumped to the console. However, when the PC gets into the catch statement (verified with breakpoint), nothing happens on the console. I am using Visual Studio 2008 in Debug mode. Thoughts are appreciated. Thanks.


CDumpContext sends output to the debugger, not to the console (see OutputDebugString for more information), and if you run under the Visual Studio debugger, the output will appear in the Output window.

If you want to also send output to the console, you can configure CDumpContext to write to a CFile by passing a pointer to a CFile object in the CDumpContext constructor.

If your application is built with the 'Use Multi-Byte Character Set' configuration option, you can use CStdioFile to write to either stdout or stderr:

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

Or, if you want to use afxDump, you can set its m_pFile member variable directly (it's declared public). For example you could put this code inside your main function:

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

But, this won't work if your app is built as Unicode because strings need to be converted to multi-byte to be written to stdout. To do the conversion, write a class that inherits 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
}

and use it like this:

CDumpFile file;
afxDump.m_pFile = &file;

A couple of other points about your code:

  1. You should ensure that the exception object is deleted in the catch block. If your CExceptionHandler class inherits MFC's CException then you should call ex->Delete(). If it doesn't, you need to delete ex.

  2. I'd advise against using the Afx prefix for own functions - you should consider this reserved for use by the MFC library, in my opinion.

I hope this helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜