I was asking on IRC the other day about SEH and __try / __except.  I was 
told that it does work if you use __try1 and __except1.  I've been 
experimenting and that's "sort of" true. But there are a lot of caveats, 
so I thought I'd write up a brief report on what I found.

TLDR: __try1 is totally incompatible with MSVC (see #1-3), fragile (see 
#7), and has serious instances of unexpected behavior (see #5).  
Strictly speaking it "works," but I certainly wouldn't use this in 
production code unless I absolutely had to.

BTW, I'm not asking for someone to 'fix' anything here.  I'm not sure 
it's possible to fix the __try1 or __except macros.  In order for this 
to work, it's going to take compiler changes, and I'm told there has 
been some resistance to adding this to the compiler (something about the 
Borland patents?).

IAC, if you are interested in experimenting, there are some things to 
know.  Here's what I found.

/* Some code using __try1 / __except1.  If run with no arguments,
   it will raise an exception.  Otherwise not. */
#include <stdio.h>
#include <errhandlingapi.h>

int foo1(int i)
{
    int j = (i - 1) * 7;

    if (j < 1)
       RaiseException(2, 1, 0, NULL);

    return j;
}

extern "C" int exc(_In_ EXCEPTION_POINTERS *lpEP);
int exc(_In_ EXCEPTION_POINTERS *lpEP)
{
    printf("Exception code: %u  Flags: %u\n", 
lpEP->ExceptionRecord->ExceptionCode, lpEP->ExceptionRecord->ExceptionFlags);
    return EXCEPTION_EXECUTE_HANDLER;
}

int main(int argc, char *argv[])
{
    printf("Using: %d\n", argc);

    __try1(exc) {
       int m = foo1(argc);
       printf("main %d\n", m);
    }
    __except1
    {
       printf("Exception\n");
    }
}

Reading the code:

1) In MSVC, the __try has no argument and the except does (the reverse 
of __try1 / __except1).  Therefor this implementation is not compatible 
with existing code designed for MSVC.

2) In MSVC, the __except takes a C code fragment that determines whether 
the exception is handled by this __except or not.  The handler that is 
passed to __try1 must be a function.  This means that unlike the MSVC 
implementation, you cannot use any of the variables from main() while 
determining whether to handle the exception.

3) Given #2, several of the MSVC macros make little sense (like 
GetExceptionInformation).  In fact, some of these currently reference 
undefined functions (like GetExceptionCode()).

4) If an exception is thrown, this code works as expected: 
printf("main") does not get executed and printf("Exception code") and 
the printf("Exception") both do.

5) If the exception is not thrown, the printf("Exception") still gets 
executed (very unexpected!).

6) Using a c++ try/catch in conjunction with __try1 results in the SE 
not being caught at all.

7) Optimization can make a real hash of this.  For example if foo1() 
gets inlined, it is no longer 'between' __try1 and __except1, so the 
exception is no longer passed to the handler.

8) Looking at the implementation of __try1:

#define __try1(pHandler) \
     __asm__ __volatile__ ("\t.l_startw:\n" \
     "\t.seh_handler __C_specific_handler, @except\n" \
     "\t.seh_handlerdata\n" \
     "\t.long 1\n" \
     "\t.rva .l_startw, .l_endw, " 
__MINGW64_STRINGIFY(__MINGW_USYMBOL(pHandler)) " ,.l_endw\n" \
     "\t.text" \
     );

The .l_startw symbol name is hard-coded.  This means you cannot use more 
than one __try1 in a function.  Using ".text" causes problems with some 
build options (-ffunction-sections).  Using ".seh_code" should resolve 
this, but requires a fairly new gas 
(https://sourceware.org/ml/binutils/2014-03/msg00260.html).

That's my experience anyway.  FWIW.

dw

------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are 
consuming the most bandwidth. Provides multi-vendor support for NetFlow, 
J-Flow, sFlow and other flows. Make informed decisions using capacity planning
reports.http://sdm.link/zohodev2dev
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to