在Delphi中进行调试时,我经常会意外地进入我不感兴趣的代码。
让我们首先说我知道你可以用F8跳过,你可以用f4跑到某一行。
示例:
function TMyClass.DoStuff():Integer;
begin
// do some stuff
bla();
end;
procedure TMyClass.Foo()
begin
if DoStuff()=0 then // press F7 when entering this line
beep;
end;
示例:我想通过按F7进入方法DoStuff(),但不是去那里,我首先进入FastMM4.FastGetMem(),这是一大堆汇编代码,显然我不感兴趣在此刻。
有几种方法可以解决这个问题,我不喜欢其中任何一种:
在“ bla ”上添加断点(如果您只想在特殊情况下进入DoStuff,几乎无用,例如迭代23498938);
不是按F7,而是手动将光标移动到“ bla ”,然后按F4(Works就这个简单的例子。实际上,它没有);
如果是FastMM:暂时禁用fastmm;
有没有办法提示我从不>有兴趣进入某个代码块,或者我总是要设置额外的断点或使用F4来避免这种情况?
我希望有一些神奇的编译器指令,比如{$ NODEBUG BEGIN / END}或类似的东西。
在大多数情况下,能够排除整个单元对我来说都是细粒度的,但是能够避免使用某些方法甚至代码行会更好。
更新:也许codegear应该引入类似 skip-points (而不是断点)的东西: - )
答案 0 :(得分:23)
有一个“神奇的nodebug开关”。 {$ D-}将禁用调试代码的生成。将它放在FastMM单元的顶部,您不会最终跟踪它。如果你最终进入了一个你不想进入的功能,SHIFT-F8会很快让你出局。 (警告:不要在堆栈代码例程中使用SHIFT-F8。可能会导致不可预知的行为.F4到底部。)
答案 1 :(得分:7)
如果您正在跳转到FastMM代码,那么就会发生内存操作。您显示的代码没有任何内存操作,因此您的问题不完整。我会试着猜出你的意思。
当子例程具有编译器管理类型的局部变量(例如字符串,接口或动态数组)时,函数序言具有非常重要的工作要做。序言也是调整输入参数的参考计数的地方。调试器代表函数begin
行中的序言。如果当前执行点是该行,并且您“进入”它,您将被带到RTL代码以管理特殊类型。 (我不希望FastMM也参与其中,但也许事情已经从我习惯的事情发生了变化。)在这种情况下,一件容易的事就是“跨越”begin
行而不是进入它;使用F8。
如果你在输入突出显示的行时真的按F7,那么你做错了。那是踩到begin
行,不是调用DoStuff
的行。因此,您是否接受了FastMM代码与DoStuff
的实现无关。要调用DoStuff
的调用,当前执行点应该 调用它的行。
如果您只想在迭代23498938上调试DoStuff
,那么您可以在该函数中设置条件断点。单击装订线以生成正常断点,然后右键单击它以显示其属性。在那里,您可以定义每次执行到达该点时将评估的条件。只有在条件为真时,调试器才会停在那里。按F8“跳过”DoStuff
调用,如果条件为真,调试器将停在那里,就像你按下F7一样。
您可以切换“使用调试DCU”选项,以避免步入大多数RTL和VCL单元。我不知道FastMM是否包含在该集合中。关键的区别在于您链接到的DCU是否使用调试信息进行编译。该设置改变库路径以包含或排除调试DCU所在的子目录。我认为您可以配置包含或排除的调试目录集,以便根据“调试DCU”设置添加或删除自定义目录集。
回到断点。您可以通过为断点指定名称来设置断点组。您可以使用高级断点在传递断点时启用或禁用命名的断点组。 (如果需要,断点组只能有一个断点。)因此,例如,如果您只想在程序中传递其他位置Y,则只想在位置X处中断,可以在X处设置禁用断点Y处的断开断点。在Y处设置“启用组”设置以启用组X.
您还可以利用已禁用的断点而无需自动启用和禁用。您的断点出现在“断点”调试器窗口中。如果您单步执行DoStuff
并且此次决定要检查bla
,请转到断点窗口并在bla
处启用断点。无需导航到bla
的实现以在那里设置断点。
有关高级断点的更多信息,请参阅几年前的Using Non-Breaking Breakpoints in Delphi和Cary Jensen撰写的文章。
答案 2 :(得分:5)
我可能错过了您的帖子,但使用FastMM4,您可以编辑FastMM4Options.Inc包含文件并删除'。'来自以下定义:
来自FastMM4Options.inc ****
{启用此选项可禁止生成调试信息 FastMM4.pas单位。这将阻止集成调试器进入 内存管理器代码。}
{$ .define NoDebugInfo}
重新编译时(可能需要构建),调试器将(应该)不再调试FastMM代码。
答案 3 :(得分:4)
使用FasmMM的预编译非调试DCU
答案 4 :(得分:3)
在项目dpr文件中,我使用
uses
{$IFNDEF DEBUG} FastMM4, {$ENDIF}
... // other units
在调试模式下排除FastMM4。在FastMM4中不需要更改,因此当我更改为其他版本时,我不必记得在FastMM中添加{$ D-}。
答案 5 :(得分:2)
AFAIK,调试器只知道您可以在选项中修改的浏览路径中的文件。因此,如果排除模块的路径,那么您对调试不感兴趣,这会产生您想要做的事情。
一个警告:代码完成还依赖于浏览路径,因此您可能会遇到代码完成在需要时不足的情况。
答案 6 :(得分:2)
虽然它不是您问题的直接答案,但您可以通过将断点设置为bla来修改您的第一个建议的解决方案,该断点仅在Foo的断点传递时启用(或者您选择的其他条件,例如迭代)计数)。然后它只会在你想要的时候打破。
顺便说一句,我发现越来越多的是我没有在断点处暂停执行,而是将变量值或堆栈转储转储到消息日志中。这样可以比变量等的实时检查更加仔细分析.FWIW。
答案 7 :(得分:0)
没有。我不相信有一种方法可以告诉调试器永远不会停留在某段代码中。没有魔术指令。
当你进入一个你不想进入的例程时,你可以做的最好的事就是使用Shift + F8,它将一直运行直到返回。然后执行F7或F8退出程序。
嗯。现在我看到了梅森的回答。学到了一些东西。谢谢,梅森。 1