CS415 数据结构与算法

Chapter 2 Programming Tutorials

| 关于   «  5. 常用调试方法   ::   目录   ::   7. 使用 Java 的 Scanner 类  »

6. 在 Eclipse 中进行调试

6.1. 在 Eclipse 中进行调试

在本教程中,我们将展示基本的调试步骤。要开始调试程序,请点击下方蓝色圆圈标注的图标来选择调试(Debug)模式。

Debug view

Figure 2.6.1: 图 1

6.1.1. 什么是调试器?

调试器(debugger)是一种软件,它允许程序员运行自己的代码,使其看起来像在正常执行一样,但同时可以在任意位置停止和暂停,以转储(dump)程序中的信息。它能让你前所未有地了解程序每一步所发生的事情。 关于调试器的更多信息,请参阅 维基百科条目。

6.1.2. 调试术语

  1. 恢复(Resume) - 恢复运行会执行代码,直到命中另一个断点或程序运行结束(图标见图 2)。

  2. 步入(Step Into) - 步入会让你进入下一个被调用的函数。例如,对上面图片中的 bst.add() 调用执行步入,会把你带到 bst 类中 add 方法的内部(图标见图 2)。

  3. 步过(Step Over) - 步过会执行当前行代码,并前进到下一行代码,在那里停止(图标见图 2)。

  4. 步出(Step Return) - 代码将一直执行到下一条返回(return)语句为止(图标见图 2)。

  5. 断点(Breakpoint) - 断点是你代码中的一个停止点。当你设置一个断点后,调试器只要运行到那里就会停止执行。你可以通过点击 Eclipse 代码窗口的左侧边栏来添加断点(见图 1)。

Debug Steps

Figure 2.6.2: 图 2

* 注 - 这里还有一些未在此文档中记录的步进函数,你可以进一步了解它们 此处。

6.1.3. 调试内存池

对于某些程序,你可能需要分析字节块。换句话说,对于一个内存区域,它表示什么,又包含哪些信息?由于多种因素的综合影响,要做到这一点可能很困难。那么我们怎样才能有意义地分析一个字节块呢?请看下面的代码。

import java.util.Random;
public class Main {

   /**
    * @param args
    */
   public static void main(String[] args) {     
      Random rdn = new Random();
      String alpha = "Zabcdefghijklmnopqrstuvwxyz"; 
      byte[] letters = new byte[1000];
       int min = 0; int max = 999;
       int amin = 0; int amax = 26;
       String loc = "";
      for(int i=0; i<40; i++) {
         int ind = rdn.nextInt(max - min + 1) + min;
         int wind = rdn.nextInt(amax - amin + 1) + amin;
         char chr = alpha.charAt(wind);
         letters[ind] = (byte) chr;
         loc += ind+" ";
      }
      System.out.println(loc);
   }

}

这个程序创建一个 1000 字节的数组,然后从 27 个字符中随机挑出一个,放到 1000 个位置中随机挑出的一个位置上。假设你想查看这个字节数组的内容。你会怎么做?Eclipse 可以让我们在变量窗口中通过内存转储来完成这件事(见图 1)。

Debug Steps

Figure 2.6.3: 图 3

默认情况下,Eclipse 会把一个字节解释为整数。

Debug Steps

Figure 2.6.4: 图 4

然而,还有很多其他解释字节值的方法。你可以通过选择 Window->Preferences 打开 Preferences 窗口(见图 5)。然后你就能选择原始转储信息。在这个例子中,我选择了 ASCII 文本,这样我就可以看到被解释为 ASCII 字符的字节值。

Debug Steps

Figure 2.6.5: 图 5

现在,当我们查看内存位置时,就能看到存储在那里的字符。我们也可以更改显示偏好设置,来查看十六进制值或无符号值。

ASCII View

Figure 2.6.6: 图 6:启用 ASCII 文本视图

Hex View

Figure 2.6.7: 图 7:启用十六进制视图

Unsiged View

Figure 2.6.8: 图 8:启用无符号视图

All Three Views

Figure 2.6.9: 图 9:启用全部三种视图

6.1.4. Eclipse 控制台

现在你可以查看内存、设置断点,甚至单步执行函数到你关心的位置。在调试 C 程序时,gdb 的命令行界面对于快速、程序化地转储信息非常方便。Eclipse 也有类似的功能。Eclipse 的 Debug Shell 窗口就是一个调试终端。如果 Debug Shell 窗口不可见,你可以通过 Window->Show View->Debug Shell 启用它。Debug Shell 窗口打开后,你可以通过右键单击并选择 Content Assist 来开启自动补全,或者按 CTRL-SPACE(类似 Eclipse 为编写代码提供的补全辅助)。Debug Shell 窗口允许你编写 Java 代码并执行它。它是一个实时窗口,你可以在其中编写代码、执行方法和演示代码,而无需重新编译。任何时候暂停你的程序,你都可以访问局部变量、修改它们,并打印出关于它们的信息。在下面的例子中,我选择把 String 类型的 args[0] (来自命令行程序的 main() 方法)打印到输出中。虽然这个特定的例子乍一看似乎没什么用,但请你想象一下,你现在正在调试一个程序。你知道出现了错误,与其停下来用修复后的代码重新编译程序,你可以快速构建替代代码并当场测试,以确保成功。

Result Of Running Code in Debug Shell

Figure 2.6.10: 图 9:Debug Shell

6.1.5. 条件断点

有时,你的错误可能是在大量处理之后才出现的。你不能只在一行代码上设置断点,因为在错误出现之前,那一行会被执行 10000 次。你真正想要的是,只有在某个其他条件(例如某个变量取某个特定值,或经过 X 次之后)成立时,才在这一行停止。然而,如果添加额外代码去捕获这些特定条件,日后忘记移除这些额外代码就会引发问题。幸运的是,许多调试器都具备只在需要时才在断点处停止的功能。

步骤 1:创建一个断点。在这个例子中,我将使用那个随机填充字符的内存池的源代码。我希望当且仅当 ind 的值为 10 时命中我的断点。

Breakpoint set

步骤 2:右键单击断点,然后选择 Breakpoint Properties(断点属性)。

步骤 3:然后你会看到一个与下图类似的界面。在断点处停止有两种选项:按命中次数(hitcount)停止,或在条件满足时停止。在这个例子中,我选择只在随机生成的索引等于 10 时才停止程序。请选择你想要的选项;如果你选择条件方式,请创建一个任意的布尔表达式作为停止条件。

Breakpoint condition

通过使用条件断点,你可以加快调试速度,并消除意外推进过远的机会。关于使用断点的更多信息,请查看 Eclipse 官方文档。

   «  5. 常用调试方法   ::   目录   ::   7. 使用 Java 的 Scanner 类  »

关闭窗口