如何在C++中检测是否连接了调试器?

6
我已经创建了一个宏,
#define DEBUG_BREAK(a) if (a) __asm int 3;

但问题是如果没有附加调试器,程序将运行不正确。
因此,我需要知道是否连接了调试器。如果有调试器,则应用程序应调用int 3。否则,不应该调用。
我该如何做到这一点?

可能是https://dev59.com/VG445IYBdhLWcg3wg6tm的重复问题。 - ZoomIn
2个回答

7

根据您的需求,最好使用正确的暴露出来的kernel32.dll函数DebugBreak。基本上按照以下方式进行。

#define DEBUG_BREAK(a) if(a) if (IsDebuggerPresent()) DebugBreak()

或者不使用 __asm int 3 例程,而使用VC提供的内在函数 __debugbreak,即:

#define DEBUG_BREAK(a) if(a) if (IsDebuggerPresent()) __debugbreak()

后者与int 3相比,在使用/clr编译时会产生差异,正如文档所指出的那样。当然,这个内在函数并不总是存在的,因此取决于您的VS/VC版本(您没有说明)。
在两种情况下,您都需要至少包含windows.h才能使用IsDebuggerPresent()
然而,这正是您需要有调试和发布版本的原因,并且可以有条件地构建它们。请记住,尽管您努力在代码中仔细放置断点,但优化器仍可能在调试器中破坏结果。原因很简单,您源代码中的某些行将不再被表示或将以确定的方式更改。因此,对于这两种情况使用同一个配置并不太合理。因此,我的意思是使用类似以下方式:
#ifdef _DEBUG
#   define DEBUG_BREAK(a) if(a) __debugbreak()
#else
#   define DEBUG_BREAK(a) do {} while(0)
#endif

5
您可以使用 CheckRemoteDebuggerPresentIsDebuggerPresent - 其中,CheckRemoteDebuggerPresent 并不一定意味着调试器在不同的机器上运行,而只是系统中存在一个可以处理断点等内容的调试进程(当使用远程调试器时,目标系统上也有一个小型进程,这就是它的来源)。
编辑:此时我强烈建议使用某种函数,而不是宏。

1
如果我使用函数,调试器会在函数中断,这不是我想要的。 - Jichao
@Useless:我需要在输入DEBUG_BREAK处中断,否则我宁愿使用Visual Studio中的断点。 - Jichao
@Jichao 点击“步进”按钮一次,应该可以让您到达放置DEBUG_BREAK的位置。除非我完全错过了什么... - Mats Petersson
1
@MatsPetersson:是的,Shift+F11可以将我发送到DEBUG_BREAK的调用者,但如果我使用宏,程序会停在正确的调用者而不是函数内部。 - Jichao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接