|
Re: C++ exceptions: msg#00032gnu.cegcc.devel
Kevin O'Connor wrote: On Thu, Jul 05, 2007 at 02:54:33AM +0100, Pedro Alves wrote:(...) Very nice. Hiding the __ehd would be great. If not possible (...) This has the advantage that it should work with C code. (I'm pretty Yep, I agree that C support is important. Earlier on, I tried to use the same __try/__except syntax that msdn But what is life without pain? Oh well, it gets hidden under some macros, so why not? :) Checkout the attached. Not pretty and easy to follow, but it works, and it allows stuff like: __TRY { int *zero; int result; zero = 0; result = *zero + *zero; } __EXCEPT_FILT (custom_filter) { printf ("except block with filter\n"); } __END_TRY or: __TRY { int *zero; int result; zero = 0; result = *zero + *zero; } __EXCEPT { printf ("except block without filter\n"); } __END_TRY or: __TRY { printf ("normal try block\n"); } __FINALLY { printf ("finally block\n"); } __END_TRY Better for portability with MSVC, where one can: #ifdef _MSVC #define __TRY __try #define __FINALLY __finally #define __EXCEPT_FILT(FILT) __except(FILT) #define __EXCEPT __except #else ... #endif (humm, in fact it could go in the exceptions.h headers.) In the tar.gz, there is also the test_eh.cc compiled so if for some reason you can't build it, at least you can try it in your device. >I still don't know why I can't leave the exception handler with >EXCEPTION_CONTINUE_EXECUTION.. Somewhat my fault for hinting wrongly. You should return with ExceptionContinueExecution which comes from the following enum: typedef enum { ExceptionContinueExecution, ExceptionContinueSearch, ExceptionNestedException, ExceptionCollidedUnwind } EXCEPTION_DISPOSITION; While these are to be used as the result of the __except filter expression: #define EXCEPTION_EXECUTE_HANDLER 1 #define EXCEPTION_CONTINUE_EXECUTION (-1) #define EXCEPTION_CONTINUE_SEARCH 0 I think the global helper functions exported could be renamed to have a similar naming like a common prefix, or whatever. -- Cheers, Pedro Alves #ifndef SEH_EXCEPTIONS_H #define SEH_EXCEPTIONS_H #include <setjmp.h> #include <windows.h> #ifdef __cplusplus extern "C" { #endif typedef int (*__seh_filter) (unsigned int code, struct _EXCEPTION_POINTERS *ep); struct eh_data { jmp_buf env; __seh_filter filter; }; #define __TRY \ do { \ struct eh_data __ehd; \ memset (&__ehd, 0, sizeof (__ehd)); \ int __in_else = 1; \ int __in_finally = 0; \ (void)__in_finally; \ while (1) \ if (!__in_else) { \ do { #define __EXCEPT_FILT(func) \ } while(0); \ end_ehandling(&__ehd); \ break; \ } else { \ __ehd.filter = (func); \ start_ehandling(&__ehd); \ if (setjmp(__ehd.env)) { \ end_ehandling(&__ehd); \ do { #define __FINALLY \ } while(0); \ end_ehandling(&__ehd); \ __in_finally = 1; \ __in_else = 1; \ } else { \ if (!__in_finally) { \ __ehd.filter = eh_default_filter; \ start_ehandling(&__ehd); \ } \ if (__in_finally || setjmp(__ehd.env)) { \ end_ehandling(&__ehd); \ do { #define __END_TRY \ } while (0); \ break; \ } \ __in_else = 0; \ } \ } while (0); #define __EXCEPT __EXCEPT_FILT(eh_default_filter) void start_ehandling(struct eh_data *d); void end_ehandling(struct eh_data *d); void init_thread_ehandling(void); void init_ehandling(void); int eh_default_filter(unsigned int code, struct _EXCEPTION_POINTERS *ep); #ifdef __cplusplus } #endif #endif #include <windows.h> #include "exceptions.h" #define UNUSED __attribute__((unused)) static DWORD handler_tls; void start_ehandling(struct eh_data *d) { TlsSetValue(handler_tls, d); } void end_ehandling(struct eh_data *d UNUSED) { TlsSetValue(handler_tls, NULL); } void init_thread_ehandling(void) { TlsSetValue(handler_tls, NULL); } void init_ehandling(void) { handler_tls = TlsAlloc(); } struct _DISPATCHER_CONTEXT; EXCEPTION_DISPOSITION eh_handler(struct _EXCEPTION_RECORD *ExceptionRecord, void *EstablisherFrame UNUSED, struct _CONTEXT *ContextRecord, struct _DISPATCHER_CONTEXT *DispatcherContext UNUSED) { struct eh_data *d = TlsGetValue(handler_tls); if (d == NULL) /* Unexpected, perhaps there is another handler installed. */ return EXCEPTION_CONTINUE_SEARCH; if (d->filter) { int ret; struct _EXCEPTION_POINTERS ep; ep.ExceptionRecord = ExceptionRecord; ep.ContextRecord = ContextRecord; ret = d->filter (ExceptionRecord->ExceptionCode, &ep); switch (ret) { case EXCEPTION_EXECUTE_HANDLER: ContextRecord->Pc = (DWORD)longjmp; ContextRecord->R0 = (DWORD)d->env; ContextRecord->R1 = 1; return ExceptionContinueExecution; case EXCEPTION_CONTINUE_EXECUTION: return ExceptionContinueExecution; case EXCEPTION_CONTINUE_SEARCH: default: return ExceptionContinueSearch; } } /* Unexpected, perhaps there is another handler installed. */ return EXCEPTION_CONTINUE_SEARCH; } int eh_default_filter(unsigned int code UNUSED, struct _EXCEPTION_POINTERS *ep UNUSED) { return EXCEPTION_EXECUTE_HANDLER; } __asm__( /* Data to be placed at start of .text section. The .init section is placed before .text with the default linker script. */ "\t.section .init\n" "\t.word eh_handler\n" "\t.word 0\n" "start_eh_text:\n" /* Data for exception handler. */ "\t.section .pdata\n" "\t.word start_eh_text\n" "\t.word 0xc0000002 | (0xFFFFF << 8)\n" /* max 22 bits for number of instructions */ /* Switch back. */ "\t.text\n" ); #include <stdio.h> #include <stdlib.h> #include <windows.h> #include "exceptions.h" static int custom_filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) { printf("in custom_filter\n"); printf("Exception: Code:%x Flags:%x Addr:%x " "SP:%x LR:%x R0:%x R1:%x R2:%x R3:%x R4:%x R5:%x R12:%x\n\n", code, (unsigned)ep->ExceptionRecord->ExceptionFlags, (unsigned)ep->ExceptionRecord->ExceptionAddress, (unsigned)ep->ContextRecord->Sp, (unsigned)ep->ContextRecord->Lr, (unsigned)ep->ContextRecord->R0, (unsigned)ep->ContextRecord->R1, (unsigned)ep->ContextRecord->R2, (unsigned)ep->ContextRecord->R3, (unsigned)ep->ContextRecord->R4, (unsigned)ep->ContextRecord->R5, (unsigned)ep->ContextRecord->R12 ); return EXCEPTION_EXECUTE_HANDLER; } static void bad() { int *zero; int result; zero = 0; result = *zero + *zero; } void test_eh (int i) { printf ("test 1\n"); printf ("arg i = %d\n", i); __TRY { bad(); } __EXCEPT { printf ("except block 1 reached\n"); } __END_TRY __TRY { int *zero; int result; zero = 0; result = *zero + *zero; } __EXCEPT_FILT (custom_filter) { printf ("except block 2 reached\n"); } __END_TRY printf ("arg i = %d\n", i); printf ("test 2\n"); __TRY { printf ("normal try block\n"); } __FINALLY { printf ("in finally (1)\n"); } __END_TRY printf ("arg i = %d\n", i); printf ("test 3\n"); __TRY { printf ("bad try block\n"); bad(); printf ("bad try block ended ?\n"); } __FINALLY { printf ("in finally (2)\n"); } __END_TRY printf ("arg i = %d\n", i); printf ("tests done\n"); } int main () { init_ehandling(); test_eh (123); return 0; } TARGET=arm-wince-mingw32ce CC=$(TARGET)-gcc CXX=$(TARGET)-g++ WARNFLAGS=-Wall -Wextra #CFLAGS=-g0 -O0 CXXFLAGS=$(CFLAGS) ALLCFLAGS=$(WARNFLAGS) $(CFLAGS) ALLCXXFLAGS=$(WARNFLAGS) $(CXXFLAGS) SOURCES=test_eh.cc Makefile exceptions.c exceptions.h OBJECTS=test_eh.o exceptions.o all: test_eh.exe clean: rm -f $(OBJECTS) test_eh.exe test_eh.exe: $(OBJECTS) $(CXX) $(OBJECTS) -o $@ $(ALLCXXFLAGS) $(LDFLAGS) exceptions.o: exceptions.c exceptions.h test_eh.o: test_eh.cc exceptions.h .c.o: $(CC) -c $< -o $@ $(ALLCFLAGS) .cpp.o: $(CXX) -c $< -o $@ $(ALLCXXFLAGS) .cc.o: $(CXX) -c $< -o $@ $(ALLCXXFLAGS) download: test_eh.exe pcp test_eh.exe ":/test_eh.exe" dist: test_eh.tar.gz test_eh.tar.gz: all $(SOURCES) rm -f $@ tar cfz $@ $(SOURCES) test_eh.exe
This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/_______________________________________________ Cegcc-devel mailing list Cegcc-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@xxxxxxxxxxxxxxxx https://lists.sourceforge.net/lists/listinfo/cegcc-devel |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | Re: C++ exceptions: 00032, Nuno Lucas |
|---|---|
| Next by Date: | Re: C++ exceptions: 00032, Pedro Alves |
| Previous by Thread: | Re: C++ exceptionsi: 00032, Kevin O'Connor |
| Next by Thread: | Re: C++ exceptions: 00032, Pedro Alves |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |