Visual Studio 2010中的程序化数据断点

9
我一直在尝试使用编程数据断点,例如CBreakpoint,通过使用SetThreadContext直接设置调试寄存器。大多数参考资料都表明,即使Visual Studio没有设置该数据断点,它仍会在遇到数据断点时停止。然而,这似乎不是Visual Studio 2010的工作方式。
当我不调试程序时,我的数据断点可以完美地工作(它会崩溃并显示STATUS_SINGLE_STEP,这是由数据断点引发的异常)。如果我用WinDbg进行调试,它也能正常停止。但是在Visual Studio 2010下调试时,它似乎只是继续执行而忽略了断点。有人在Windows 7下使用Visual Studio 2010设置编程数据断点的经验吗?是否需要做些什么才能让它们停下来?(我尝试将STATUS_SINGLE_STEP添加到“首次机会异常”列表中,但行为没有任何变化。)
另外,在调试器中,我可能会吞掉STATUS_SINGLE_STEP异常吗?结构化异常处理程序会在调试器看到之前阻止掉异常吗?这是x86_64程序的影响吗?在Visual Studio 2010设置中需要做些什么吗?

Visual Studio可能只监视来自软件源的调试中断,即INT 2C,您需要通过WriteProcessMemory设置(我不知道__debugbreak是否适用于您的用例)。 - Necrolis
@Necrolis 我正在从自己的进程中完成所有这些操作。而且我并不试图停在特定的指令上... - John Calsbeek
3个回答

2

经过一些测试,我在win7 x64上使用VS 2010 SP1 Ultimate,使用32位二进制代码可以正确地触发硬件断点(包括有和没有SEH的情况)。然而,当使用64位二进制代码时,它无法捕获单步执行(我不得不修改一些类型才能使其编译通过)。

深入挖掘后,似乎是VS表现出了奇怪的行为,因为虽然它不能捕获单步执行,但我无法正确地跨越一段会触发硬件断点的代码区域。

我有一种感觉,即该库在x64下未正确设置DR寄存器,这可能与x64中SetThreadContext的更改有关。

更新

再进行一些尝试后,我注意到您使用的库在设置或获取线程上下文之前并没有暂停线程,MSDN说这是一个大忌:

在运行线程时无法获得有效的上下文。在调用GetThreadContext之前,请使用SuspendThread函数暂停线程。

然而,即使使用另一个库,该库正确地暂停目标线程并执行其所有调用而不出错,仍然无法让VS捕获BP,这使我认为您使用的库不仅有缺陷,而且VS的x64调试器也有缺陷。


我已经验证了代码正确地设置了DR寄存器,或者至少我认为是这样的,因为它在没有调试器和在WinDbg下都能正确地捕获。在WinDbg下,我可以看到DR寄存器正确地改变了。但是我应该查看VS中的寄存器窗格,以查看它们是否被接受,或者VS是否正在重置它们... - John Calsbeek
我也看到过警告,不应该获取/设置正在运行的线程的上下文,这完全有道理。然而,它可以正常工作,我至少看到一个人猜测如果你使用CONTEXT_DEBUG_REGISTERS,那么这不是一个问题。(这对我来说很有道理:通常你会破坏指令指针和所有内容,但唯一会干扰调试寄存器的东西就是,嗯,调试器。) - John Calsbeek

0

你的项目是否启用了混合(本机和托管)调试?我进入了项目属性->配置属性->调试器->调试类型设置为“混合”

这里找到了答案。


1
虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。仅有链接的答案如果链接页面更改可能会变得无效。 - Roman Marusyk
1
@MegaTron是正确的 - 请总结与问题和您的答案相关的链接部分。 - kdbanman

-3
有一个名为DebugBreak()的函数,你可以用它来在MSVC 2010下以编程的方式中断你的执行,但它会停止在DebugBreak(反汇编代码)内部。所以如果你只想在你的代码中断,使用__asm int 3非常简单,并且适用于所有兼容英特尔CPU的情况。
另外需要注意,在使用DebugBreak()__asm int 3之前,先使用IsDebuggerPresent(),以避免运行时错误(当然你已经知道这一点了! :))。

1
这个问题是关于数据断点而不是代码断点的。 - John Calsbeek

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