Location: ProgrammingUnlimited.Net :: Software :: LibSEH
LibSEH - a Windows SEH compatibility library
.

NOTE: THIS INFORMATION MAY NO LONGER BE RELEVANT AS CLANG HAS PARTIAL SEH SUPPORT FOR BOTH X86 AND X86_64! THIS PAGE REMAINS HERE FOR HISTORICAL PURPOSES.

Note: This is alpha grade code. But then again, it might work very well. It seems to work in my limited testing so far.

News
.

As of 12-05-2011, the latest version is v0.0.4, which fixes several issues.

About LibSEH
.

LibSEH is a compatibility layer that allows one to utilize the Structured Exception Handling facility found in Windows within GNU C/C++ for Windows (MINGW32, CYGWIN). In other compilers, SEH is built into the compiler as a language extension. In other words, this syntax is not standard C or C++, where standard in this case includes any ANSI standard. Usually, support for this feature is implemented through __try, __except, and __finally compound statements. Here is an example:

      #include <windows.h>
      #include <stdio.h>

      int ExceptionFilter(unsigned int code, unsigned int excToFilter)
      {
          if(code == excToFilter) return EXCEPTION_EXECUTE_HANDLER;
          else                    return EXCEPTION_CONTINUE_SEARCH;
      }

      int main()
      {
          int x = 0;
          int y = 4;
          __try
          {
              y /= x;
          }
          __except(ExceptionFilter(GetExceptionCode(), EXCEPTION_INT_DIVIDE_BY_ZERO)) 
          {
              printf("Divide by zero exception.\n");
          }

          return 0;
      }

    

This is only supported in Microsoft C/C++ and Digital Mars C/C++. These are not standard language constructs.

LibSEH allows programs intended for GNU C/C++ to utilize this feature, with a high degree of source-level compatibility, resulting in minimal changes to existing code. To modify the above program in order to compile it on GNU C/C++ with LibSEH, a few changes need to be made:

      #include <windows.h>
      #include <stdio.h>
      #include <seh.h>       /* The LibSEH header needs to be included */

      int ExceptionFilter(unsigned int code, unsigned int excToFilter)
      {
          if(code == excToFilter) return EXCEPTION_EXECUTE_HANDLER;
          else                    return EXCEPTION_CONTINUE_SEARCH;
      }

      int main()
      {
          int x = 0;
          int y = 4;
          __seh_try   /* __try becomes __seh_try */
          {
              y /= x;
          }
          __seh_except(ExceptionFilter(GetExceptionCode(),   /* __except becomes __seh_except */
              EXCEPTION_INT_DIVIDE_BY_ZERO)) 
          {
              printf("Divide by zero exception.\n");
          }
          __seh_end_except   /* This must terminate all __seh_except blocks */

          return 0;
      }
    

The seh.h header includes other headers, and when preprocessed under Microsoft C/C++ and Digital Mars C/C++ (untested), the __seh_end_except is defined as a no-op. It does have meaning though for GNU C/C++, and the program will not compile without it (and since the above are preprocessor macros, strange compiler errors will result, so keep this in mind when something doesn't compile).

All of this allows the same source to be compiled on GNU C/C++ and Microsoft C/C++ (and most likely, Digital Mars C/C++).

The library also supports the __try/ __finally combination:

      int main()
      {
          int x = 0;
          int y = 4;
          __seh_try
          {
              __seh_try {
                  y /= x;
              }
              __seh_finally {
                  printf("Leaving __seh_try/__seh_finally compound statement.\n");
              }
              __seh_end_finally          /* NOTE THE __seh_end_finally, also required */
          }
          __seh_except(ExceptionFilter(GetExceptionCode(), EXCEPTION_INT_DIVIDE_BY_ZERO)) 
          {
              printf("Divide by zero exception.\n");
          }
          __seh_end_except 

          return 0;
      }
    

The __seh_finally block will be called if an exception is raised, and the exception is handled in a block farther up on the stack. It's also called if no exception occurs.

KNOWN DIFFERENCES BETWEEN LibSEH AND BUILT IN IMPLEMENTATIONS OF SEH:
.

LibSEH does not have the exact same behavior as builtin SEH in Microsoft C/C++. Here are some of the currently known differences (and I could be incorrect, as I haven't tested all of these):

These differences only affect when LibSEH is really being used, like when using GNU C/C++.

A note concerning C++: LibSEH does not unwind the stack in the same way that the C++ runtime library does, and as a consequence, destructors are not called when objects go out of scope from stack unwinding when dealing with an exception. This can lead to resource leaks if one isn't careful. The library does include a C++ interface (which translates SEH (system) exceptions into C++ exceptions), however.

Changes
.

v0.0.4 fixes some macro conflicts with libstdc++ as well as several other issues and adds the __seh_leave macro.

v0.0.3 fixes some GCC 3.x compatibility issues.

Versions v0.0.2 and up are compatible with GCC 4.x, whereas v0.0.1 is not. v0.0.2 also fixes some issues that apply to optimized builds.

When Problems Occur
.

If a problem occurs with a program that uses libseh in terms of SEH (exceptions not being caught that occur, stack variables mysteriously changing in subroutines that use __seh_try/__seh_except, etc), it is suggested that one compile the application without optimizations. Bug reports are always welcome.

Download (alpha)
.

libseh-0.0.4.zip (Source code)

libseh-0.0.3.zip (Source code)

libseh-0.0.2.zip (Source code)

libseh-0.0.1.zip (Source code)

...... ...... ...... ...... ...... ...... ...... ...... ....... ....... ...... ...... ....... ....... ...... ...... ...... ...... ...... ...... ...... ...... ....... ....... ...... ...... ....... ....... ...... ...... ...... ...... ...... ...... ...... ...... ....... ....... ...... ...... ....... .......

.