更高堆栈帧上的条件断点

Sne*_*tel 6 debugging conditional-breakpoint visual-c++

在MSVC++调试器中,是否可以在一个函数中创建断点,其条件取决于来自其他堆栈帧的局部变量?我经常发现自己在一个函数中创建一个条件断点,当该断点命中时,我启用另一个断点(我希望在退出当前函数调用之前触发)并继续.这很费时且容易出错.

我过去采用的一种方法是将有问题的变量写入全局,并将该全局用作条件.但这需要重新编译,并且不适用于多线程代码.

Han*_*ant 6

是的,这在技术上是可行的.没关系,请注意,您必须告诉调试器取消引用指针以获取另一个堆栈帧中的局部变量的值.

一个简单的例子:

#include "stdafx.h"
#include <iostream>

void foo() {
    for (int ix = 0; ix < 5; ++ix) {
        std::cout << ix << " ";                 // <=== Conditional breakpoint here
    }
}

void bar() {
    for (int jx = 0; jx < 5; ++jx) {
        std::cout << jx << ": ";                // <=== Start with a breakpoint here
        foo();
        std::cout << std::endl;
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    bar();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

首先需要获取要设置条件的变量的地址.在bar()中的指示行上设置断点.当它命中时,评估&jx并复制该值.

现在使用该值设置条件断点.我用了:

  *(int*)0x0073fbc8 == 2 && ix == 3
Run Code Online (Sandbox Code Playgroud)

其中0x0073fbc8是我在第一个断点处获得的值.或者你可以从基指针寄存器使它相对.设置一个无条件断点,当它命中时,使用Debug + Windows + Registers查看EBP值.从&jx值中减去它.我用了:

  *(int*)(ebp+0xd8) == 2 && ix == 3
Run Code Online (Sandbox Code Playgroud)

两者都运作良好.请注意,您需要关闭ASLR以使Debug构建有一些希望这些地址从一次运行到另一次运行是可重复的.项目+属性,链接器,高级,随机化基地址=否.