Выгрузка полезных данных в консоль при обнаружении исключения - PullRequest
1 голос
/ 10 ноября 2010

У меня есть класс 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);
}

Это функция Dump члена CExceptionHandler:

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

Я бы хотел, чтобы собранная отладочная информация выводилась на консоль. Однако, когда ПК попадает в оператор catch (проверяется с помощью точки останова), на консоли ничего не происходит. Я использую Visual Studio 2008 в режиме отладки. Мысли ценятся. Благодаря.

1 Ответ

3 голосов
/ 11 ноября 2010

CDumpContext отправляет вывод в отладчик, а не в консоль (см. OutputDebugString для получения дополнительной информации), и если вы работаете в отладчике Visual Studio, вывод появится в Вывод Окно.

Если вы также хотите отправить вывод на консоль, вы можете настроить CDumpContext для записи в CFile, передав указатель на объект CFile в конструкторе CDumpContext .

Если ваше приложение построено с опцией конфигурации «Использовать многобайтовый набор символов», вы можете использовать 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, потому что строки должны быть преобразованы в многобайтовые для записи в stdout. Чтобы выполнить преобразование, напишите класс, который наследует 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->Delete(). Если это не так, вам нужно delete ex.

  2. Я бы не советовал использовать префикс Afx для собственных функций - на мой взгляд, вы должны учитывать это, зарезервировано для использования библиотекой MFC.

Надеюсь, это поможет!

...