5

调试时如何在满足 if 语句中的条件时停止?例如:

if (!check()) {
  int a = 0;
}

int a = 0; 是虚拟代码,然后我在那里放了一个断点。如果我在一个空的 if 循环中放置一个断点,调试器不会停在那里,它只会在它可以执行的指令处停止。即使你做 int a; 只是一个声明,它不会停止。

我可以用其他方式而不是编写虚拟代码来做到这一点吗?

谢谢

4

2 回答 2

10

我可以用其他方式而不是编写虚拟代码来做到这一点吗?

是的!

在调试器中,您应该能够添加断点并将其设置为仅在满足特定条件时才中断。如何执行此操作取决于您的 IDE,但在我的 IDE 中,我可以右键单击代码编辑器排水沟或单独的断点窗口中的断点,然后从弹出菜单中选择属性。然后我得到这个对话框:

带有条件集的断点属性对话框

您可以看到我设置了“条件”属性,每次代码遇到该断点时都会对其进行评估 - 但断点只会在条件为true. 即,如果一切正常时返回,则check()返回true!check()将使其中断。check()false

如果经常调用此方法,这往往会稍微减慢您的程序,因为通常要评估这样的表达式,调试器必须(内部)中断并评估某些内容。但它的功能很简洁。请注意您还可以设置的所有其他属性,并且在单击“高级”按钮后,甚至还没有看到对话框的样子......

要回答您的其他问题:

如果我在一个空的 if 循环中放置一个断点,调试器不会停在那里,它只会在它可以执行的指令处停止。即使你做 int a; 只是一个声明,它不会停止。

如果 if 块(不是循环)是空的,那么它就没有什么可以停止的了。它只能在实际代码上停止。 int a;只是一个变量声明;对于简单类型,实际上没有为此生成任何代码。(例如,它可以用于更复杂的类型,MyClass a;因为这会调用构造函数。)即使您编写更多代码:

if (!check()) {
  int a;
  a = 5;
  b = a;
}

您的编译器可能仍然不会为此生成任何代码,因为它可能会发现代码实际上从未执行任何操作。这在一定程度上取决于您的优化设置,但即使没有任何特定的优化设置,一些编译器也会对其进行优化。

有时,由于各种原因(有时只是条件评估的速度),中断代码而不是使用 IDE 会很方便。在这种情况下,我倾向于使用函数调用来中断,因为编译器不会知道该函数不会修改程序的状态,也无法对其进行优化:

if (!check()) {
  rand(); // <- breakpoint here
}

但通常充分利用您的 IDE 和调试器功能是一种更好的方法。

编辑:因为这得到了赞成(谢谢大家),为了完整起见,我想我会添加另一种方法。软件/调试器断点与中断 3 一起出现,由调试器修补。 汇编指令只有一个字节长,因此int 3可以在任何其他指令上进行修补;当程序中断时,可以临时修补旧指令。但是除了调试器在运行中将其放入之外,您还可以将其放入代码中。

换句话说,您可以通过类似的方式强制您的程序中断代码(并被调试器捕获;如果您不在调试器下运行,这可能会导致问题;通常,您的程序将中止)。语法取决于您的环境:

if (!check()) {
  __asm int 3
}

甚至更好的是,避免依赖于环境的代码,许多 C++ 编译器具有内在函数或宏,例如DebugBreak();__debugbreak您可以像这样使用它们:

if (!check()) {
  DebugBreak();
}

当您在调试器下运行程序时,您会发现该行的执行中断。

几乎没有理由正常使用它。我见过的一个自定义断言处理程序在断言失败时会中断调试器,但允许之后继续执行。

于 2013-07-10T10:04:33.357 回答
0

使用断言。它用于调试时错误检查。如果条件为假(等于零),则执行立即停止。

于 2013-07-10T09:49:57.087 回答