在Delphi中无法在Exit语句处设置断点?

3

我尝试在Exit语句处设置断点,如下所示:

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
begin
  I := 5;

  if I = 5 then
    Exit;

end;

但是当程序启动时,断点会变成一个红色的十字,表示它不可用。为什么?我正在使用项目的“Debug”版本并使用“Run”按钮来调试该项目。

我认为您无法在类似于ExitBreakContinue的流程控制“过程”上设置断点。它们不是真正的过程,而更像是编译器特殊处理的关键字。但是,您可以在此类“过程”上面的下一行适当位置设置断点。[我怀疑Embarcadero可以选择实现这个功能,但可能并不完全简单,并且需要可能并不那么严重。] - Andreas Rejbrand
2
有可能是由于在 if 语句 后面没有代码,优化器在编译之前删除了退出语句,因为它在这个特定的代码中没有用途。尝试在退出后添加一些代码,我相信您在 Exit 上设置的断点应该可以工作。 - SilverWarior
1
@SilverWarior "将Exit调用包围在begin..end中应该是可以的" - 但实际上不行。只有添加一些无用的额外代码,例如另一个if语句,才会生成一些指令,您可以在其上设置断点。 - Stefan Glienke
通常情况下,您可以很好地在“Exit”上设置断点。这里的问题是无用的代码。由于您初始化了“I = 5;”,然后测试“if I = 5”,然后立即“Exit”,编译器足够聪明,只需删除整个方法体-它什么也不做,只意味着根本不需要首先调用它。您也无法在完全空的方法或过程中设置断点。 - Ken White
当使用扩展版本并伴随函数结果如“Exit(True);”时,您可以在函数内部的EXIT上设置断点。 - Uwe Raabe
显示剩余10条评论
2个回答

6

与 HeartWare 建议的使用条件断点相反(性能受影响,具体取决于代码的执行频率),您可以将代码更改为:

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
begin
  I := 5;
  if I = 5 then begin
    asm nop end; // <== put breakpoint here
    Exit;
  end;
end;

这提供了一个方便的位置来放置断点。

我也使用那个 :-) - HeartWare
3
我的是“sleep(0)” ;) - Ken Bourassa
我一直使用Inc(NoOpCount),其中NoOpCount是一个全局变量。我认为编译器不会优化掉对全局变量的更改... - MartynA
这会导致额外的性能损失吗,包括速度和文件大小,因为有这样一个nop语句? - alancc
另一个选择是声明一个空函数为内联函数用于发布,而对于调试则不进行内联。这种方式只会在编译调试时生成代码。但这样做会更加复杂。 - dummzeuch
显示剩余4条评论

4
您无法可靠地在EXIT(或CONTINUE或BREAK)上设置断点,因为它们不是通常意义上的语句。
但是,您可以在IF行上设置断点,然后右键单击该断点的红点,选择“断点属性”,并在条件字段中输入与您的IF语句相同的条件。

Conditional Breakpoint

这样做会稍微减慢执行速度(如果条件断点在循环内部,那么会更慢),但只有在满足条件时才会激活断点(实际上,每次命中断点都会停止程序,但如果设置了条件,调试器将评估该表达式并继续执行而不通知您,除非满足条件)。
当然,这只是一个简化的例子,但通常情况下,您可以在这些情况下使用条件断点来克服无法在确切的EXIT语句上设置断点的限制。

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