16

GCC supports Setjump-longjump (sjlj) and Dwarf2 table-based unwinding (dw2) exception handling models. What is the difference between the two models and how to choose the appropriate model? Why is Dwarf2 table-based unwinding (dw2) the more efficient model? I understand that the two models cannot be mixed.

Reference: Technology Preview: gcc-4.2.1-sjlj -2

bhadra
  • 12,887
  • 10
  • 54
  • 47

2 Answers2

17

Well, dwarf2 builds up tables for every function, that contain what the callee saved registers are and where in the stack they are saved, and where the frame pointer/return address in the callstack is, and some other stuff. If you use dwarf2, the compiler can use those information and effectively restore registers, and jump back to callers in the event of an exception. The backends need to provide information in their implementations' prologue generating code, to tell GCC which registers are callee-saved, and when the frame pointer was saved and such stuff.

Using setjmp/longjmp is just a hack. Since setjmp/longjmp does not know about the structure of the function throwing, it will restore all registers saved in the jump-buffer by setjmp, even if they were not overridden by the throwing function. I'm not really an expert for this, but i think it's obvious that this will not be efficient. Also, every time you start a try block, setjmp has to be called to set up the buffer containing the saved registers, while when using dwarf2, the compiler already provides all necessary information at compile time.

If the backends do not provide the necessary information, GCC will automatically fall-back to setjmp/longjmp based exception handling.

Note i'm not a GCC expert. I just ported the toolchain to some easy processor of my professor, including GCC. I hope i could help you a bit.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • Notice that there exist http://www.nongnu.org/libunwind/, which has an efficient `setjmp` implementation that is itself based on dwarf tables. So `setjmp` then just needs to store the stackpointer and leave the remainder to the already working dwarf unwinder. – Johannes Schaub - litb Feb 17 '14 at 17:52
11

Avoid sjlj. Every "try" block will call setjmp which saves registers, a performance hit even when no exceptions are raised. Using tables, the normal flow of control incurs no execution cost. Only when an exception is raised does the exception handling mechanism have to grovel through the tables to figure out what to do.

  • Hello themis. I am creating an app and my main compiler is mingw. I also use MSVC to create DLL to access features that only MSVC can compile. From MinGw code, I have an object that is created in my windowProcedure CALLBACK in WM_CREATE. This object's constructor throws an exception if some error; which is doing now. The code for creating the window is in a try catch block. However I am not seeing the exception being raised and I am experiencing undefined behaviour. Can you recommend me a book that explains how MinGw and MSVC exceptions work? – user13947194 Oct 17 '21 at 00:38