Does DebugBreak work to launch the debugger, or doesn’t it?

Jorge asked why the Debug­Break function stopped working. Specifically, why it doesn't launch the Visual Studio debugger.

Okay, first of all, the primary purpose of the Debug­Break function is not to launch the debugger. The primary purpose of the Debug­Break function is to trigger a break into any attached debugger. That still works the same as it always did.

The behavior Jorge asks about is a second-order side effect of the Debug­Break function.

When you perform a Debug­Break, the EXCEPTION_BREAKPOINT exception is raised. If a debugger is installed, it will intercept this exception and interpret it as a request to break into the debugger. If a debugger is not installed, then the exception is processed like any other exception, and any installed handler could step in and say, "Oh, yeah, EXCEPTION_BREAKPOINT. No problem. I'll handle that."

If a debugger is not installed and no code in the process handles the exception, then the exception goes to the current unhandled exception filter, and the default unhandled exception filter checks with Windows Error Reporting, and then displays a dialog box to inform the user of the problem.

If a just-in-time debugger is installed, that dialog box has an extra Debug button:

Contoso Deluxe

Contoso Deluxe has stopped working

A problem caused the program to stop working correctly. Windows will close the program and notify you if a solution is available.

Debug   Close program

Clicking the Debug button launches your just-in-time debugger.

Notice that once you get past the point where no attached debugger has intercepted the EXCEPTION_BREAKPOINT exception, the rest of the processing doesn't treat the breakpoint exception differently from any other exception. In other words, instead of calling Debug­Break, you could have dereferenced a null pointer, written to a read-only page, executed an invalid instruction, or called Raise­Exception. Anything that causes an exception to be raised goes through the same sequence of events, and at the end of the day will show the same dialog box.

The Debug­Break function is not a "Launch the just-in-time debugger" function. It's a very specific kind of "try to crash the program" function that debuggers understand and intercept. But if there's no debugger attached, then the program crashes, and when a program crashes (for whatever reason), the just-in-time debugger gets a chance to step in.

Comments (19)
  1. GL says:

    Reminder: The `data:` was eaten again! BTW the buttons have strange layout.

    1. Ugh. The server software apparently thinks that DIVs are always block elements (even when set to inline), so it randomly inserts P elements. Will see what I can do to fool it.

      1. Martin Bonner says:

        If you want an inline DIV, could you just call it SPAN? (Or is there some subtle difference.)

        1. SPANs cannot have borders by default.

          1. Neil says:

            Presumably the same server software is preventing you from using button-like elements?

          2. I used to use button-like elements, but stopped because if you clicked them, it would submit a comment!

      2. GL says:

        The window art is working now but I guess there are still unmatched tags in the document. In this blog entry, the “Comments You can use simple markup such as …” is placed on the right of the main article, instead of below, like it does in all other entries.

        1. Found it and fixed, thanks.

  2. Roman says:

    But why did it stop working, though? :-)

  3. IanBoyd says:

    I use:

    if (IsDebuggerPresent())

    I took the cue from the Application Verifier, which throws OutputDebugString followed by a DebugBreak to get your attention when it’s found something wrong.

  4. henke37 says:

    I could’ve sworn that there was indeed a default exception handler for this one. That silently swallowed it. Must’ve been self delusion at its finest.

    1. laonianren says:

      Me too! It’s a mass hallucination. Perhaps we were both fooled by the “Debug” in DebugBreak? Or it was once true?

      I tried it on Windows 10. Curiously, if the breakpoint happens early in WinMain the program dies silently. After the program has fully started I get the expected “… has stopped working” dialog.

  5. Anton says:

    .NET applications have Debugger.Launch(), which seems to be rather more reliable. SSCLI doesn’t show how it works, though.

    1. Zarat says:

      CoreCLR does have an implementation of .NET “Debugger.Launch” – you can follow it a bit across several files, down to “Debugger::LaunchDebuggerForUser” in src/debug/ee/debugger.cpp – in this file you can find the whole implementation spread across a lot of functions. It has fallbacks to DebugBreak, but also “knows” how to launch a “just in time debugger”.

    2. Zarat says:

      The part you are looking for is probably in CoreCLR in src/ToolBox/superpmi/superpmi/jitdebugger.cpp “GetDebuggerSettingInfoWorker” which reads out what debugger has been registered on the machine for “just in time debugging”

    3. poizan42 says:

      It just uses the value Debugger from the registry key HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug

  6. Mihai says:

    Just a curiosity: is this still done via int 3?

    1. AlexShalimov says:

      Yes, at least on VS 2012:
      000007FEFD4131F0 xchg ax,ax
      000007FEFD4131F2 int 3
      000007FEFD4131F3 ret

      1. Someone says:

        DebugBreak is a function eported by kernel32.dll. Why do you think that the VisualStudio version will influence the code in that DLL?

Comments are closed.

Skip to main content