SEH and C++ Exceptions – catch all in one

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

.


Environment:
  Visual C++ 5.0 & SP3, Windows NT 4.0 & SP5, Unicode, MBCS

This article describes how to handle SE and C++ exception together.

Motivation

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 {

  // do something ...

  p[0] = 0;

  // do something ...

  } catch (CdbException dbError) {

  //handle it

  } 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.

Download

Download demo project – 16 KB

Download source – 2 KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read