I'm writing a native mode application (think: link /subsystem:native
). This means I can't use anything from kernel32.dll, which (apparently) means nothing from the C runtime libraries. Mostly that's not a problem for me as everything I need is in ntdll.dll. The code is written and working.
However, I'm writing the code in c++, and there's the question of what to do with exception handling. I believe the intent for native mode applications is to use SEH, which is what I've done. But that's not quite working.
If I compile without /EHa, my destructors don't get called when I RtlRaiseException. But if I do compile with /EHa, I'm getting an undefined symbol (unresolved external symbol __CxxFrameHandler4), which apparently only exists in the C runtime.
(How) can I compile my c++ code to support unwinding while still building a native mode application?
Edit: VC has 4 possible settings for exception handling, all of which have problems in this context:
Yes with SEH Exceptions (/EHa)
- As mentioned above, this results in unresolved external symbol __CxxFrameHandler4.Yes (/EHsc)
- 2 unresolved symbols: __CxxFrameHandler4 & __std_terminateYes with Extern C functions (/EHs)
- Same 2 unresolveds as /EHscNo
- No unresolved symbols, but destructors don't get called when exceptions get raised.
I wondered if I could link to the non-dll version of the C runtime. After all, if everything's embedded in my executable, it won't need to load any dlls when running at boot time, right?
So, I tried linking in libvcruntime.lib (the apparent home of __CxxFrameHandler4). The good news is that __CxxFrameHandler4 is no longer unresolved. The bad news is that gave me an additional 55 unresolved symbols. This list includes items like __imp_TlsAlloc
and __imp_TlsGetValue
which are clearly from kernel32.dll (and thus unavailable to me).
I'm prepared to use either C++ exceptions or SEH, but I can't get either to work in this context.
I see a number of exception-related functions exported in ntdll. Maybe there's some other exception handling mechanism I'm supposed to be hooking into?
Edit2: Since __CxxFrameHandler4 isn't working for me, I tried disabling the new exception handling (/d2FH4-
). The only effect this had was to change the unresolved symbol to __CxxFrameHandler3. Not the result I was hoping for.
I'm out of ideas here. If there's some way to unwind the stack without using kernel32, I'm not finding it. The fact that there are exported functions in ntdll with "Exception" in their name suggests there might be, but perhaps not. Perhaps the intent there was always "C" code where destructors aren't a thing.
If anyone has any new things to try or a new place to look, I'd appreciate it. Or even an authoritative source that says it can't be done. At least then I'd know.