为什么条件断点会使我的程序运行速度如此之慢?

问题描述 投票:0回答:7

当我调试循环内出错的东西时,比如在第 600 次迭代时,必须对每个循环进行中断可能会很痛苦。因此,我尝试设置一个条件断点,仅在 I = 600 时才中断。这可行,但现在几乎需要一整分钟才能到达该点,而在此之前几乎是瞬时的。这是怎么回事,有什么办法可以解决吗?

delphi debugging breakpoints
7个回答
24
投票

当您遇到断点时,Windows 会停止进程并通知调试器。它必须切换上下文,评估条件,决定不,您不想收到有关它的通知,重新启动进程并切换回来。这可能需要很多处理器周期。如果您在紧密循环中执行此操作,则所需的处理器周期将比循环的一次迭代多几个数量级。

如果您愿意稍微修改一下代码,有一种方法可以在不产生所有这些开销的情况下执行条件断点。

if <condition here> then
  asm int 3 end;

这是一个简单的汇编指令,手动向操作系统发送断点通知。现在您可以在程序内评估您的状况,而无需切换上下文。只要确保用完后再次将其取出即可。如果 int 3 在未连接到调试器的程序中发生错误,则会引发异常。


8
投票

它会减慢速度,因为每次您到达该点时,它都必须检查您的状况。

我倾向于做的是临时创建另一个像这样的变量(在 C 中,但在 Delphi 中应该可行)。

int xyzzynum = 600;
while (true) {
    doSomething();
    if (--xyzzynum == 0)
        xyzzynum = xyzzynum;
}

然后我在

"xyzzynum = xyzzynum;"
行放置一个非条件断点。

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

您可以使条件变得尽可能复杂。


5
投票

根据 Mason 的回答,您可以仅在程序是使用定义的调试条件构建的情况下编译 int 3 汇编器:

{$ifdef debug}
{$message warn 'debug breakpoint present in code'}
if <condition here> then
  asm int 3 end;
{$endif}

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

我还包含了 $message 编译器指令,因此您在编译时会看到一条警告,让您知道代码仍然存在。如果您在使用 int 3 的任何地方都这样做,您将获得一个很好的位置列表,您可以双击该列表直接进入有问题的代码。

N@


3
投票

Mason的解释非常好。
通过测试您在调试器下运行,可以使他的代码变得更安全一点: if (DebugHook <> 0) and <your specific condition here> then asm int 3 end;

当应用程序正常运行时,这不会执行任何操作;如果应用程序在调试器下运行(无论是从 IDE 启动还是附加到调试器),则会停止。
如果您不在调试器下,则使用布尔快捷方式

<your specific condition here>
甚至不会被评估。

    


1
投票


0
投票

可以加速这一过程的一种方法是,将条件后跟一个没有副作用的操作直接放入代码中,并在该操作上中断。完成后请记住删除条件和操作。


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.