skip to Main Content

Situation:

C++ app developed with Visual Studio 2022 dies in Release mode only when debugger is detached. Now, while I may know the typical scenarios where this might be happening the code base is too immense for me to do any per-line code reviews. So, I set Windbg as post-mortem debugger in hopes of finding where it dies.

Now, shed some light onto me, please.

Question:

How do I see the exact reason why a fatal exception was thrown? Any way to browse through the recent exceptions?

Discussion

The funny thing in my case is that, this multi-threaded app, after the exception is caught by WinDbg launching in post-mortem mode.. the app continues to run…. I need to pause execution.. so I wonder what throws the exception.. and why does the app continue code execution after it was caught by WindDBG (without WindDBG set as post-mortem debugger and thus without it catching the exception – the app simply dies).

Update:

The only suspicious thing I am shown by WinDbg right after it is invoked is:

WARNING: Continuing a non-continuable exception

3

Answers


  1. Chosen as BEST ANSWER

    For whatever the reason, my Visual Studio 2022 continued to generate the DEBUG pre-processor directive, in release mode.

    That on the other hand caused setThreadName() invocations being compiled into the binary in Release mode.

    Of course, these caused an exception being fired,- one that for whatever the reason, was not clearly visible in WinDbg, when using the default configuration.

    Now, I am thankful to @LexLi for pointing me in the right direction of using WinDbg in non-invasive mode.

    Only in non-invasive mode was I able to see proper stack-frames as thus able to notice what was indeed triggering the exception.

    So, in my answer I will focus on how to enable WindDbg to act as a Post-Mortem debugger in non-invasive mode (the default is invasive), as there's no easy tangible way to change that.

    1. first make WinDbg act as the default Just-In-Time post-mortem debugger. To achieve that, execute windbg -I as an Administrator.

    2. Now, fire up Regedit and head over to:

      HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionAeDebug

    3. edit the Debugger value and add a parameter -pv, so in my case the value ends up being:

      "C:Program Files (x86)Windows Kits10Debuggersx64windbg.exe" -pv -p %ld -e %ld -g


  2. Threading issues are the bane of a bug-fixers existence! Especially when you cannot attach a debugger;

    You’re going to have to resort to producing a debug build, with extra logging – what I like to refer to as printf() debugging

    You mention attaching WindDBG – do you have a stack trace that you can work from? Use this as your starting point, and throw in a lot of std::printf lines, dumping appriopriate variables and see how you go from there.

    Login or Signup to reply.
  3. First: why would a debugger change the behavior? Well, it’s certainly not desirable, but you can’t do much about it.

    1. A C++ app started under the debugger uses a different memory layout. Due to that, buffer overflows or underflows may change which other variables are affected. It’s UB, so anything can happen, and that anything may change with the memory layout. "Appearing to succeed" is a valid form of UB.

    2. The debugger registers itself for exception handling. This may affect the timing quite a bit. Especially in a multithreaded environment, adding a debugger can change things. (Adding printf statements as suggested in another answer may change timing as well)

    Partial mitigations are:

    1. Attach the debugger after running the application. This will give the unmodified CRT memory layout.
    2. Attaching the debugger in non-invasive mode may, as suggested by yourself.

    Full mitigation, IMHO:

    Instead of attaching a debugger, let Windows create a crash dump when the application dies, using WER LocalDumps (requires: you don’t have an unhandled exception handler).

    That way you get a crash dump file (.DMP) which you can analyze later. Additional benefit over live debugging: you can send it to someone else to help you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search