Download demo project - 15 KbDownload source files - 2 KbMotivation
Everybody sometimes need to write as robust code as possible. The simplest
way, in these cases, is to use exception handling. But most code is wrote in
C++/MFC, with C++ exception handling (e.g. CdbException
). With
SEH, it is not possible to catch C++ exception, and C++ typed exception can not
catch SE selectively, because it is not typed in a way of C++. Solution with
catch(...)
is not useful, because you will not know
'type' of exception. SE is possible to catch like unsigned int typed C++
exception, but this solution is not very nice.
Description of solution
I was looking for a method to handle SE and C++ exception together. I found
function
typedef void (*_se_translator_function)( unsigned int, struct _EXCEPTION_POINTERS* );
In MSDN you can find following description:
The _set_se_translator
function
provides a way to handle Win32 exceptions (C structured exceptions) as C++ typed
exceptions. To allow each C exception to be handled by a C++ catch handler, first define a C exception "wrapper" class that
can be used, or derived from, in order to attribute a specific class type to a C
exception. To use this class, install a custom C exception translator function
that is called by the internal exception-handling mechanism each time a C
exception is raised. Within your translator function, you can throw any typed
exception that can be caught by a matching C++ catch
handler.
And now, it is enough to write wrapper class (I think, my class is quite
better than class provided by documentation for _set_se_translator
):
class CSeException : public CException
{
DECLARE_DYNAMIC(CSeException)
public:
CSeException(UINT nSeCode, _EXCEPTION_POINTERS* pExcPointers);
CSeException(CSeException & CseExc);
UINT GetSeCode(void);
_EXCEPTION_POINTERS* GetSePointers(void);
PVOID GetExceptionAddress(void);
void Delete(void);
int ReportError(UINT nType = MB_OK, UINT nIDHelp = 0);
BOOL GetErrorMessage(CString & CsErrDescr, PUINT pnHelpContext = NULL);
BOOL GetErrorMessage(LPTSTR lpszError,
UINT nMaxError,
PUINT pnHelpContext = NULL);
private:
UINT m_nSeCode;
_EXCEPTION_POINTERS* m_pExcPointers;
};
And my own translator function:
void SeTranslator(UINT nSeCode, _EXCEPTION_POINTERS* pExcPointers)
{
throw new CSeException(nSeCode,pExcPointers);
}
How does it work?
When SE is raised, then it is called our own translator function - if it was
installed through _se_translator_function
. This translator function
simply throw exception again, but now it is our wrapper class exception filled
with useful information.
Description of CSeException
CSeException
class is based on CException
class provided by MFC. I overwrite some of useful methods, but it is working
same way like any other exception class based on CException
class - you can find description in documentation provided by Visual C++.
Usage
At first of all you need to install SeTranslator
function,
in every thread of your application. Translator function is thread specific, it
means it is not globally set in application. In single thread application it is
possible to install it in constructor of application class (as I do in demo
program), however in multithreading application it is best place to install
translator function at the beginnings of every thread. When translator function
is installed, then it is possible to write code like this:
char *p = NULL;
try {
p[0] = 0;
} catch (CdbException dbError) {
} catch(CSeException *e) {
e->ReportError(MB_OK | MB_ICONSTOP);
e->Delete();
}
CSeException
class is Unicode and MBCS strings compliant.
Please note, delete CSeException
in catch()
block,
because it is dynamically allocated by translator function.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.