paint-brush
像高级开发人员一样调试:调试程序控制流经过@shai.almog
895 讀數
895 讀數

像高级开发人员一样调试:调试程序控制流

经过 Shai Almog7m2022/12/14
Read on Terminal Reader
Read this story w/o Javascript

太長; 讀書

控制流不仅仅是跳过。您可以在调试时“跳转”到任意代码偏移量以重现复杂的状态和行为!
featured image - 像高级开发人员一样调试:调试程序控制流
Shai Almog HackerNoon profile picture

截至目前,我发布了课程的前 3 个视频,明天将发布第四个。我计划每周在 YouTube 上发布两个视频以最大限度地提高影响力,但在这里,我每周只在博客上发布一节课以避免过度饱和。


我拍摄了大约 4 小时的视频内容,但仍未完成八个模块中的第二个模块。本课程将非常详细和密集。


我现在正在课程平台上工作,进展顺利,希望能尽快在这里发布。当您阅读本文时,它可能已经上线了!


对我来说,课程平台的用户体验令人满意很重要。所以我尽可能避免使用 DRM。希望人们会尊重这一点以及我为此付出的努力。


我正在使用 GraalVM 在 Spring Boot 3 上构建课程平台,因此理想情况下它会精简、快速且非常简单。我计划将 YouTube 上的视频作为非公开视频托管,以提供良好的观看体验。


这意味着开发者可能会背叛我的信任并分享未列出的视频。我希望他们不会。


我的理由是低开销和出色的性能。我还想在几年内免费提供该课程。通过使用 YouTube,我可以通过公开视频使课程免费。


以下视频讨论了调试中的控制流。这从基础开始,但可以深入到跳转到行、强制返回等。这些工具可以显着改变我们调试代码的方式。


不要忘记查看我的并订阅YouTube 频道以观看未来的视频!

成绩单

欢迎回到 Scale 调试的第二部分,您可以在其中学习调试的秘密技巧。


在本节中,我们将讨论调试的最基本方面。我们遇到了一个断点。怎么办?

好吧,这就是调试器让我们控制流程以研究一切如何在受控环境中工作的地方。


那么今天的议程是什么?


我们将讨论单步执行和进入代码,我希望您熟悉此列表中的大部分内容。我们中断控制流的最后两项您可能不熟悉。我很确定你们中的大多数人都不熟悉议程上的最后一项。我怎么知道?请继续关注并找出答案!

跨越、进入、退出和强制

Step over 是最基本的控制流形式。我们让行中的代码执行,然后我们可以在变量窗格中检查结果。它简单易行。


在这种情况下,我只是按了几次这里的按钮,但我也可以只按 F8 来获得相同的效果......


接下来,我们将讨论两个不同的操作,即进入和相关的退出。进入我们调用的方法。请注意,如果没有进入该步骤的方法,则 into 的行为类似于 step over。


我们有两个步进操作。常规步骤和通常以相同方式作用的强制步骤。当我们想要进入 IntelliJ 通常会跳过的 API 时,我们需要强制版本。我们可以按 F7 进入一个方法。我们可以按 Shift F7 强制进入。


当我们看完了一个方法,不在乎剩下的,我们就可以出去了。这将执行方法的其余部分并返回。


请注意,如果我们在返回之前有一个断点,它仍会像我们在本例中看到的那样停在断点处。我们可以在此处按此按钮退出,或者我们可以按 shift-F8 执行相同的操作。

继续并运行到光标处

Continue 继续执行项目,直到再次命中断点。这也称为简历。这是一个我们经常使用的简单功能。您可以在此处按特殊版本的播放按钮继续。快捷键也很有用,因为我们经常使用它,它是 F9。


Run to cursor 让我们跳过不感兴趣的行并到达重要的代码。我们可以在该行设置断点以获得相同的效果,但这有时更方便,因为它不需要设置和取消设置断点。


我们可以按此按钮运行到光标处,也可以使用 ALT-F9 作为此功能的快捷方式。

强制返回并抛出异常

此功能在 IntelliJ/IDEA 中称为强制返回。


要查看强制返回选项,我们右键单击堆栈跟踪可以看到一组选项。一个更有趣的选项是丢帧,我很快就会展示。


请注意 throw exception 选项,它与 force return 相同,但它从方法中抛出异常。


单击此选项后,我会看到一个对话框,用于输入方法的返回值。这让我可以更改从方法返回的值,这在我想要调试难以重现的错误时非常有用。


想象一下这样一种情况,客户发生故障,但您无法重现它。在这种情况下,我可以通过从该方法返回不同的值来模拟客户可能遇到的情况。


在这里,值是一个布尔变量,所以很简单。但是您的代码可能会返回一个对象;使用这种技术,您可以用任意值替换该对象。一个很好的例子是 null,如果此方法返回 null,它会重现我的用户遇到的问题吗?


类似地,throw exception 允许我们重现边缘情况,例如由于任意失败而引发异常。


一旦我们按下 OK,我们将返回一个不同的值。在这种情况下,我处于方法的边缘,但我本可以在方法开始时完成它并完全跳过方法的执行。


这让我们可以模拟方法可能失败的情况,但我们想模拟它的行为。如果我们不能重现客户所看到的行为,那是有道理的。我们可以使用这样的工具进行模拟。

掉帧

丢帧几乎是革命性的,但它更像是一个“巧妙的技巧”。在这里,我错误地进入了一个方法。糟糕,我不想那样做。我想在介入之前改变一些东西……幸运的是有丢帧。


我们看到我可以在右键菜单中找到它;您也可以单击此处触发它。


丢帧有效地丢掉栈帧。这是一个撤消操作。但事实并非如此。它无法撤消我们进入的方法中发生的状态更改。


因此,如果您进入方法并且不在堆栈上的变量发生了更改,它们将保持更改状态。


堆栈上的变量是方法声明或接受作为参数的那些变量,这些变量将被重置。但是,如果这些变量之一指向一个对象,那么该对象将驻留在堆中,并且无法通过展开堆栈来重置那里的更改。


这仍然是一个非常有用的功能,类似于强制返回,但它会返回到当前行,而不是下一行。因此,它不会返回值。


这比那更好!

跳转到行

跳转到行是 IntelliJ 中的一个秘密功能。它有效,但开发人员不知道。您需要安装 Jump to Line 插件才能使用它。由于它的安装量相对较低,我认为人们只是不知道它的存在。因为这是必备插件。它将改变您调试的方式!


使用跳转到行,我们可以将当前指令指针移动到方法中的不同位置。我们可以拖动左边的箭头将执行带到一个新的位置。请注意,这在两个方向上都有效,我可以来回移动当前执行。


这不会执行中间的代码,它实际上将当前指令移动到一个新位置。太酷了,我必须再次展示它......


如果您看到错误,只需将执行拖回并重现它。您可以更改变量值并一遍又一遍地重现问题,直到您完全理解它为止。


我们可以跳过失败的代码等。这很壮观。我不需要重新编译代码。如果你遇到过不小心跨过一条线的情况,“糟糕。那不是我想要的。”

然后停止调试器并从头开始。这是适合您的插件。这发生在每个人身上!


我们可以将执行拖回并重做。这绝对是太棒了!

最后

在下一个视频中,我们将简要讨论手表。我们将在本系列的第六个视频中更深入地探讨它。敬请期待!


如果您有任何疑问,请使用评论部分。谢谢!