# Destructor is run
testcpp11unwind:::call_A()
#> Error: oh no!
#> hello from the destructor!
# Destructor is NOT run
testcpp11unwind:::call_B()
#> Error: oh no!Note that cpp_A() and cpp_B() on their own are seemingly innocuous
code that a developer is likely to write without thinking twice about
it.
The destructor of a doesn’t run in the cpp_B() case because:
call_B()sets up a try/catch through the entry macrosfn()callsunwind_protect()and setsshould_unwind_protect = FALSER_UnwindProtect()is used to callcall_A(), and asetjmp()is used to be able to recover fromlongjmp()scall_A()sets up a try/catch through the entry macroscpp_A()is calledais createdstop()callsunwind_protect(), butshould_unwind_protect = FALSEso it does NOT useR_UnwindProtect()orsetjmp()stop()ends up callingRf_error(), causing alongjmp()- Because
should_unwind_protect = FALSE, thelongjmp()is not caught instop(). Instead we jump alllll the way back to wherefn()calledunwind_protect()andR_UnwindProtect(). This skips over thecpp_A()frame whereashould have been destructed on the way out. VERY BAD!