为什么条件断点会使我的程序减慢太多?

14 delphi debugging breakpoints

当我在循环中调试出错的东西时,比如在第600次迭代中,对每个循环都要打破是一件痛苦的事.所以我尝试设置一个条件断点,只有在I = 600时才会中断.这样可行,但现在需要几乎整整一分钟才能到达那个点,在此之前几乎是瞬间.发生了什么事,有什么方法可以解决它吗?

Mas*_*ler 22

当您遇到断点时,Windows会停止该过程并通知调试器.它必须切换上下文,评估条件,决定不,您不希望收到通知,重新启动进程并切换回来.这可能需要很多处理器周期.如果你是在一个紧凑的循环中进行它,它将比循环的一次迭代花费几个数量级的处理器周期.

如果你愿意稍微搞乱你的代码,有一种方法可以在不产生所有这些开销的情况下完成条件断点.

if <condition here> then
  asm int 3 end;
Run Code Online (Sandbox Code Playgroud)

这是一个简单的汇编指令,可手动向OS发送断点通知.现在,您可以在不切换上下文的情况下评估程序内的条件.只要确保在完成后再将其取出.如果int 3在未连接到调试器的程序内部发生,则会引发异常.

  • 这是一个糟糕的答案!您不希望冒险在程序中留下错误的int 3.看看Pax的答案 - 你设置一个断点的无害线.如果它在生产代码中结束,这不会造成麻烦. (2认同)

pax*_*blo 6

它减慢了速度,因为每次达到这一点,它都必须检查你的情况.

我倾向于暂时创建另一个这样的变量(在C中,但在Delphi中应该可行).

int xyzzynum = 600;
while (true) {
    doSomething();
    if (--xyzzynum == 0)
        xyzzynum = xyzzynum;
}
Run Code Online (Sandbox Code Playgroud)

然后我在线上放了一个非条件断点"xyzzynum = xyzzynum;".

程序以全速运行,直到它循环600次,因为调试器正在执行正常的断点中断,而不是每次检查条件.

您可以根据需要使条件变得复杂.


Nat*_*Nat 5

继梅森的回答之后,如果程序是使用定义的调试条件构建的,您可以只编译 int 3 汇编程序:

{$ifdef debug}
{$message warn 'debug breakpoint present in code'}
if <condition here> then
  asm int 3 end;
{$endif}
Run Code Online (Sandbox Code Playgroud)

因此,当您在 ide 中进行调试时,您可以在项目选项中设置调试条件。当您为客户构建最终产品时(使用构建脚本?),您不会包含该符号,因此它不会被编译。

我还包含了 $message 编译器指令,所以当你编译时你会看到一个警告,让你知道代码仍然存在。如果你在任何使用 int 3 的地方都这样做,你就会有一个很好的地方列表,你可以双击这些地方直接带你到有问题的代码。

N@


Dan*_*ite 1

任何调试器中的条件断点(我只是在这里猜测)都要求每次遇到断点时,进程都会在程序和调试器之间来回翻转。这个过程很耗时,但我认为你无能为力。