Интерфейс:
// SeException.h - interface of the CSeException class
// Copyright (c) 2004-2008 by Elijah Zarezky,
// All rights reserved.
// Portions copyright (c) 2000 by Martin Ziacek.
#if !defined(__SeException_h)
#define __SeException_h
#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
#endif // _MSC_VER
class CSeException: public CException
{
DECLARE_DYNAMIC(CSeException)
// construction/destruction
public:
CSeException(UINT uCode, _EXCEPTION_POINTERS* pXcptPtrs);
virtual ~CSeException(void);
// copying/assignment
public:
CSeException(const CSeException& src);
CSeException& operator =(const CSeException& src);
// operations
public:
void Delete(void);
virtual BOOL GetErrorMessage(LPTSTR pszDest, UINT uMaxLen, UINT* puHelpCtx = NULL);
virtual int ReportError(UINT fuType = MB_OK, UINT uHelpID = 0);
// SEH translator
public:
static void Translator(UINT uCode, _EXCEPTION_POINTERS* pXcptPtrs);
// accessibility
public:
UINT GetCode(void);
LPCTSTR GetDescription(void);
void* GetAddress(void);
// attributes
protected:
UINT m_uCode;
_EXCEPTION_POINTERS m_xcptPtrs;
// implementation helpers
private:
BOOL FormatErrorMessage(CString& strDest);
// diagnostic services
#if defined(_DEBUG)
public:
virtual void AssertValid(void) const;
virtual void Dump(CDumpContext& dumpCtx) const;
#endif
};
#endif // __SeException_h
Реализация:
// SeException.cpp - implementation of the CSeException class
// Copyright (c) 2004-2008 by Elijah Zarezky,
// All rights reserved.
// Portions copyright (c) 2000 by Martin Ziacek.
#include "SeException.h"
#if defined(__INTEL_COMPILER)
// remark #279: controlling expression is constant
#pragma warning(disable: 279)
// remark #981: operands are evaluated in unspecified order
#pragma warning(disable: 981)
#endif // __INTEL_COMPILER
#if defined(_DEBUG)
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif // _DEBUG
// object model
IMPLEMENT_DYNAMIC(CSeException, CException)
CSeException::CSeException(UINT uCode, _EXCEPTION_POINTERS* pXcptPtrs):
m_uCode(uCode),
m_xcptPtrs(*pXcptPtrs)
{
}
CSeException::~CSeException(void)
{
}
CSeException::CSeException(const CSeException& src):
m_uCode(src.m_uCode),
m_xcptPtrs(src.m_xcptPtrs)
{
}
CSeException& CSeException::operator =(const CSeException& src)
{
m_uCode = src.m_uCode;
m_xcptPtrs = src.m_xcptPtrs;
return (*this);
}
void CSeException::Delete(void)
{
#if defined(_DEBUG)
m_bReadyForDelete = TRUE;
#endif // _DEBUG
delete this;
}
BOOL CSeException::GetErrorMessage(LPTSTR pszDest, UINT uMaxLen, UINT* puHelpCtx)
{
CString strTemp;
ASSERT(pszDest != NULL);
ASSERT(AfxIsValidString(pszDest, uMaxLen));
if (puHelpCtx != NULL)
{
*puHelpCtx = 0;
}
FormatErrorMessage(strTemp);
if (!strTemp.IsEmpty())
{
::lstrcpyn(pszDest, strTemp, uMaxLen);
return (TRUE);
}
else
{
return (FALSE);
}
}
int CSeException::ReportError(UINT fuType, UINT uHelpID)
{
CString strError;
FormatErrorMessage(strError);
return (AfxMessageBox(strError, fuType, uHelpID));
}
void CSeException::Translator(UINT uCode, _EXCEPTION_POINTERS* pXcptPtrs)
{
CSeException* pXcpt = new CSeException(uCode, pXcptPtrs);
throw pXcpt;
}
UINT CSeException::GetCode(void)
{
return (m_uCode);
}
LPCTSTR CSeException::GetDescription(void)
{
switch (m_uCode)
{
case EXCEPTION_ACCESS_VIOLATION:
return (_T("Access violation"));
case EXCEPTION_DATATYPE_MISALIGNMENT:
return (_T("EXCEPTION_DATATYPE_MISALIGNMENT"));
case EXCEPTION_BREAKPOINT:
return (_T("EXCEPTION_BREAKPOINT"));
case EXCEPTION_SINGLE_STEP:
return (_T("EXCEPTION_SINGLE_STEP"));
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
return (_T("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
case EXCEPTION_FLT_DENORMAL_OPERAND:
return (_T("EXCEPTION_FLT_DENORMAL_OPERAND"));
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
return (_T("Floating point divide by zero"));
case EXCEPTION_FLT_INEXACT_RESULT:
return (_T("Floating point inexact result"));
case EXCEPTION_FLT_INVALID_OPERATION:
return (_T("EXCEPTION_FLT_INVALID_OPERATION"));
case EXCEPTION_FLT_OVERFLOW:
return (_T("Floating point overflow"));
case EXCEPTION_FLT_STACK_CHECK:
return (_T("EXCEPTION_FLT_STACK_CHECK"));
case EXCEPTION_FLT_UNDERFLOW:
return (_T("Floating point underflow"));
case EXCEPTION_INT_DIVIDE_BY_ZERO:
return (_T("Integer divide by zero"));
case EXCEPTION_INT_OVERFLOW:
return (_T("Integer overflow"));
case EXCEPTION_PRIV_INSTRUCTION:
return (_T("EXCEPTION_PRIV_INSTRUCTION"));
case EXCEPTION_IN_PAGE_ERROR:
return (_T("EXCEPTION_IN_PAGE_ERROR"));
case EXCEPTION_ILLEGAL_INSTRUCTION:
return (_T("EXCEPTION_ILLEGAL_INSTRUCTION"));
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
return (_T("EXCEPTION_NONCONTINUABLE_EXCEPTION"));
case EXCEPTION_STACK_OVERFLOW:
return (_T("Stack overflow"));
case EXCEPTION_INVALID_DISPOSITION:
return (_T("EXCEPTION_INVALID_DISPOSITION"));
case EXCEPTION_GUARD_PAGE:
return (_T("EXCEPTION_GUARD_PAGE"));
case EXCEPTION_INVALID_HANDLE:
return (_T("EXCEPTION_INVALID_HANDLE"));
default:
return (_T(">>> unrecognized <<<"));
}
}
void* CSeException::GetAddress(void)
{
return (m_xcptPtrs.ExceptionRecord->ExceptionAddress);
}
BOOL CSeException::FormatErrorMessage(CString& strDest)
{
static TCHAR szFormat[] = _T("Exception 0x%08lX at address 0x%08lX:\n%s.");
strDest.Empty();
if (m_uCode == EXCEPTION_ACCESS_VIOLATION)
{
// special case
CString strDescr(GetDescription());
ULONG_PTR* xcptInfo = m_xcptPtrs.ExceptionRecord->ExceptionInformation;
LPCTSTR pszMemOp = xcptInfo[0] != 0 ? _T("write") : _T("read");
CString strDetails;
strDetails.Format(_T("\x20(unable to %s at address 0x%08lX)"), pszMemOp, xcptInfo[1]);
strDescr += strDetails;
strDest.Format(szFormat, m_uCode, GetAddress(), static_cast<LPCTSTR>(strDescr));
}
else
{
// common case
strDest.Format(szFormat, m_uCode, GetAddress(), GetDescription());
}
return (!strDest.IsEmpty());
}
#if defined(_DEBUG)
void CSeException::AssertValid(void) const
{
// first perform inherited validity check...
CException::AssertValid();
// ...and then verify own state as well
}
void CSeException::Dump(CDumpContext& dumpCtx) const
{
try
{
// first invoke inherited dumper...
CException::Dump(dumpCtx);
// ...and then dump own unique members
dumpCtx << "m_uCode = " << m_uCode;
}
catch (CFileException* pXcpt)
{
pXcpt->ReportError();
pXcpt->Delete();
}
}
#endif // _DEBUG
Пример использования:
// install SEH translator
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
_set_se_translator(&CSeException::Translator);
...
}
...
void foo(void)
{
try
{
int* pnDummy = NULL;
int nCrash = *pnDummy;
}
catch (CSeException* pXcpt)
{
pXcpt->ReportError();
pXcpt->Delete();
}
}
|