在VC++中,在正确的时间点将调试器附加到进程的最佳方法是什么?

在VC++中,在正确的时间点将调试器附加到进程的最佳方法是什么?,c++,debugging,visual-c++,debugbreak,C++,Debugging,Visual C++,Debugbreak,调试时,有时需要附加一个已经运行的进程,而不是在调试器中启动应用程序 对我来说,通常会进行Sleep或MessageBox调用,以便更容易附加调试器。我担心其中一些可能最终会被用于源代码控制 在仍然延迟足够的时间以便可以将调试器附加到正在运行的进程的同时,要避免这种情况,最好的方法是什么 使用ifdef_调试保护睡眠或消息框是一种方法,但我想知道是否有更好的方法 在睡眠中,你也会遇到一个问题,那就是你可能无法及时入睡。如果使用MessageBox,您可能会遇到远程调试的问题,或者调试没有可视GU

调试时,有时需要附加一个已经运行的进程,而不是在调试器中启动应用程序

对我来说,通常会进行Sleep或MessageBox调用,以便更容易附加调试器。我担心其中一些可能最终会被用于源代码控制

在仍然延迟足够的时间以便可以将调试器附加到正在运行的进程的同时,要避免这种情况,最好的方法是什么

使用ifdef_调试保护睡眠或消息框是一种方法,但我想知道是否有更好的方法


在睡眠中,你也会遇到一个问题,那就是你可能无法及时入睡。如果使用MessageBox,您可能会遇到远程调试的问题,或者调试没有可视GUI示例作为服务在Vista上运行的进程,您可以使用DebugBreak,请检查以下链接:

查阅:

DebugBreak、\uu DebugBreak和朋友


静态void timeToChase{uuuu asm{int 3;};}

必须在“恰好正确的点”附加是一种痛苦。。。一种选择是在代码中添加显式DebugBreak语句以强制解决问题,使用ifdef_DEBUG保护它们是个好主意。我们使用一个可以调用DebugBreak的ASSERT宏,所以您可以只写ASSERTfalse

另一个要考虑的选项是使用“图像文件执行选项”自动启动调试器。请参阅此文件和文档

__asm int 3 

这个硬断点将打开调试对话框,让您连接到进程。在ifdef_DEBUG中包装它,您只会在调试版本中点击它。

Freddy和Reoa有正确的解决方案。但是我想添加一个不使用MessageBox的原因

显示MessageBox只会部分停止应用程序。因为您正在显示UI,所以消息泵仍在程序中至少一个线程上运行。因此,如果您的代码执行以下任一操作

通过Windows消息进行通信 具有非平凡的UI 是多线程的 实际上,您将在一种状态下请求调试器,但在完全不同的状态下附加到程序。这可能会导致令人困惑的情况和错误


我们最近在我们的代码库中做了一个更改,从不显示MessageBox,以便于出于这个原因中断。对于一个非平凡的应用程序,它会产生非常糟糕的行为

要在特定点附加调试器,您有几个选项:

最简单的方法就是调用DebugBreak,它相当于_asm int 3,但也适用于其他体系结构。如果我没记错的话,MSVC for x64不允许内联汇编。这将打开实时调试器窗口,您可以从已注册的调试器(即Visual Studio)中选择要附加到进程的调试器

或者,您可以引入对Sleep的调用,从而使您有机会附加调试器。您应该使用ifdef_DEBUG来解决这个问题,以确保您实际上没有附带此代码

一个问题:为什么不能从IDE运行代码?它是服务还是IIS加载的DLL或类似文件

在本例中,您可以签出ImageFileExecutionOptions注册表项,该注册表项允许您在进程启动时附加调试器


如果为此使用cdb,则可以将其配置为WinDbg实例的服务器或客户端,并以这种方式进行调试。在过去,我使用WinDbg作为内核调试器,并使用ImageFileExecutionOptions以命名进程启动ntsd-d来实现这一点。这会导致WinDbg进入用户模式。这有时是一种有用的技术。

我有时使用的另一种变体是

while( !::IsDebuggerPresent() )
    ::Sleep( 100 ); // to avoid 100% CPU load

它应该静默地等待,直到您将调试器连接到进程。

如果u debugbreak或debugbreak对您有效,那么我认为这可能是最好的方法

但是,我遇到了一些情况,由于未知的原因,uuu debugbreak只是立即终止程序,而不是等待调试器连接。我尝试了各种方法来解决注册表黑客等问题,但似乎没有任何效果。在本例中,我试图调试的进程不是直接从命令行启动的,而是由Java程序启动的,这可能与此相关

无论如何,在这种情况下,我使用了这种方法,似乎效果很好:

void waitForDebuggerToConnect() {
    #ifdef _DEBUG
    static volatile bool spin = true;
    while (spin)
    {}
    #endif
}
调用此函数后,我的程序将无限期挂起在“while”循环中。然后我可以调用VC++调试器并附加到进程。然后我可以使用“全部断开”来停止所有线程。然后,我可以找到卡住线程的调用堆栈,可以使用调试器检查顶部框架,可以检查“spin”的值,然后将其设置为“false”。此时,我可以退出此函数和/或设置断点,然后恢复部分或所有线程的运行。

@JaredPar:谢谢
这是我的解释。谢谢,我做到了!既然您对代码为什么不能从IDE运行感到好奇,那么在我的例子中,这是因为我正在调试我编写的DLL,该DLL是由第三方应用程序注入到进程中的,这两个应用程序都不是我直接控制的。DLL注入到的进程不是由我启动的,它是我启动的进程的子进程,因此我也不能将调试器附加到它。DebugBreak只会导致进程崩溃,而不会显示JIT调试器对话框。但是一会儿!IsDebuggerPresent;调试中断;似乎有办法。相关: