On Wed, 01 Apr 2009 11:22:22 -0700, Ian Lance Taylor <i...@google.com> wrote: > "Vincent R." <foru...@smartmobili.com> writes: > >>> gcc will do the right thing if you put statements in an exception >>> region. >> >> Hum how gcc can do that kind of things, is it some kind of voodoo ? >> __except is not implemented yet and is more than a language construct >> because it's an >> OS thing. >> So maybe I need to say it once again, instructions inside __except needs >> to >> be >> put inside a function by the compiler . > > Can you explain why that is? I don't know how SEH works; how does the > OS get involved? > Yes I can but I will talk only about table-based SEH available on RISC(ARM, SH, MIPS) and x64 architecture Mechanism is different on x86.
Usually with C++ exceptions you cannot catch for instance NULL pointer exception ie if you write something like that : DWORD* ptr = NULL; try { *ptr = 0X42; // access violation } catch(...) { } it will segfault. With SEH you can catch that kind of errors and that's why it's so interesting in embedded world To be able to do it, it means OS is involved. When OS is initialized it registers exception table and when an exception is raised it will look what is Program Counter of the current process. Then he will look inside a specific PE section that list address and length of each function available in the binary and check if the function has SEH. If it has SEH it will look inside another table that will tell him to jump to the associated filter function. So when you declare this : int _tmain(int argc, _TCHAR* argv[]) { DWORD* ptr = NULL; // NULL pointer __try { puts("in try"); *ptr = 0x4242; // causes an access violation exception; } __except(puts("in filter"), EXCEPTION_EXECUTE_HANDLER){ puts("in except"); } puts("world"); return 0; } you will get the generated code as if you had written like that .text ------------------------------------------ int wmain(int argc, _TCHAR* argv[]) { DWORD* ptr = NULL; // NULL pointer BEGINTRY: { puts("in try"); *ptr = 0x4242; // causes an access violation exception; ENDTRY: } goto AEB; JMPTGT: puts("in except"); AEB: puts("world"); return 0; } int filter_func(unsigned int code, struct _EXCEPTION_POINTERS *ep) { puts("in filter_func"); return EXCEPTION_EXECUTE_HANDLER; } .xdata (or .pdata on wince) ---------------------------------------- FuncStart PrologLen FuncLen ThirtyTwoBit ExceptionFlag Comment 00011008 0x4 0x15 1 1 wmain 0001105c 0x1 0x9 1 0 So from this table we know that wmain starts at address 00011008 and finish at address 00011008 + 0x15 = 0001101D So when access violation is raised OS kernel looks Program Counter, in the above case it happens at 0001102C and he knows that problem is in wmain and that this function has an associated SEH. Then kernel looks inside another table that will tell him to jump to filter_func(). The filter_func return a value to indicate if it want to handle this exception and if yes it will jump to Jump target address (JMPTGT label). So code inside __except braces will be executed. Hope you understand better.