1 00:00:00,000 --> 00:00:00,309 2 00:00:00,309 --> 00:00:02,350 [? DAN ARMADARAS:?]你好, 我[?丹Armadaras?]。 3 00:00:02,350 --> 00:00:04,410 今天,我们要 在看调试。 4 00:00:04,410 --> 00:00:06,697 我们不仅要 谈一些技巧, 5 00:00:06,697 --> 00:00:09,280 而且我们要看看 一些特性包含 6 00:00:09,280 --> 00:00:14,170 在CS50 IDE允许范围内 您可以轻松地调试程序。 7 00:00:14,170 --> 00:00:16,272 >> 只是一个例子, 东西可以去错 8 00:00:16,272 --> 00:00:18,730 它实际上是什么 我们已经看到了。 9 00:00:18,730 --> 00:00:23,200 在这种情况下,这是一个C程序 接受来自用户的整数, 10 00:00:23,200 --> 00:00:27,580 除以它由两个,并提供了 输出给用户。 11 00:00:27,580 --> 00:00:30,610 现在从我们所看到的 在前面讲课, 12 00:00:30,610 --> 00:00:34,370 我们知道,这实际上会导致 特定类型的划分问题 13 00:00:34,370 --> 00:00:35,860 当我们有奇数。 14 00:00:35,860 --> 00:00:40,330 >> 具体来说,我们就扔掉 小数点后的任何东西。 15 00:00:40,330 --> 00:00:43,170 现在,我们知道,这 恰好是这种情况。 16 00:00:43,170 --> 00:00:47,430 如果我们运行它,我们可以确认 我们的怀疑,首先,通过编译。 17 00:00:47,430 --> 00:00:50,460 然后,通过运行和 输入奇数。 18 00:00:50,460 --> 00:00:51,720 >> 这是什么新鲜事。 19 00:00:51,720 --> 00:00:54,490 但是,这实际上是一个 例如一个错误的 20 00:00:54,490 --> 00:00:58,810 可以在一个更大的计划存在 这变得更难追查。 21 00:00:58,810 --> 00:01:02,640 尽管我们知道是什么问题 是,事情的真正症结所在 22 00:01:02,640 --> 00:01:06,250 可能会试图确定 具体在哪里出现错误, 23 00:01:06,250 --> 00:01:09,750 确定是什么问题 是,然后将其固定。 24 00:01:09,750 --> 00:01:14,400 因此,提供这作为一个例子 的可能是什么东西 25 00:01:14,400 --> 00:01:19,030 我们已经知道,但可以埋 内的代码的其他元素。 26 00:01:19,030 --> 00:01:23,090 >> 所以打开这个其他来源 代码文件作为例子, 27 00:01:23,090 --> 00:01:27,165 这种划分问题是现在 一个较大的程序的一部分。 28 00:01:27,165 --> 00:01:29,040 不过可能有点 有点做作,和我们 29 00:01:29,040 --> 00:01:31,076 可能能够容易地 识别它,特别是 30 00:01:31,076 --> 00:01:32,450 因为我们刚才谈到的这一点。 31 00:01:32,450 --> 00:01:38,250 但是,我们可以计算出,这 问题可以在更大的范围存在。 32 00:01:38,250 --> 00:01:45,450 >> 如果我编译这个和现在 运行它,输入一个奇数, 33 00:01:45,450 --> 00:01:49,816 我们可以看到,我们没有得到准确 我们可能预期的输出。 34 00:01:49,816 --> 00:01:51,690 在这种特殊情况下, 我们可以说,我们 35 00:01:51,690 --> 00:01:56,060 要计算所有号码 从一个到某个特定数量。 36 00:01:56,060 --> 00:01:58,130 我们可以看到,我们 有各种各样的问题 37 00:01:58,130 --> 00:02:03,880 在这里,如果我们输,简单地说,0 和1时,我们提供的5输入。 38 00:02:03,880 --> 00:02:07,380 >> 因此,我们已经知道, 有一个问题在这里。 39 00:02:07,380 --> 00:02:11,662 但是大家可能不知道准确 其中,这个问题确实存在。 40 00:02:11,662 --> 00:02:13,620 现在的方法之一是 我们可以尝试解决这个问题 41 00:02:13,620 --> 00:02:15,745 是,我们的东西 已经被引入。 42 00:02:15,745 --> 00:02:18,880 我们可以只使用它在更大的规模。 43 00:02:18,880 --> 00:02:21,680 >> 在第14行,我们有 这个printf函数, 44 00:02:21,680 --> 00:02:25,620 这使我们能够打印出状态 的各种信息。 45 00:02:25,620 --> 00:02:28,880 这是东西,你 应在程序中利用 46 00:02:28,880 --> 00:02:33,100 要尽量弄清楚到底是什么 发生在各行代码。 47 00:02:33,100 --> 00:02:36,350 因此,即使这不是 我们实际上最终的输出 48 00:02:36,350 --> 00:02:39,830 要生产出 这个计划,我们仍然 49 00:02:39,830 --> 00:02:42,300 可能有一些调试 声明我们 50 00:02:42,300 --> 00:02:46,970 可以揣摩正是 正在发生的事情对我们的代码中。 51 00:02:46,970 --> 00:02:51,210 >> 因此,在这种情况下,我会 printf输出调试标签。 52 00:02:51,210 --> 00:02:53,540 在这种情况下,这是 只是一个调试字符串 53 00:02:53,540 --> 00:02:56,840 说我了,把使之成为 在我的代码的输出非常明确 54 00:02:56,840 --> 00:02:59,200 它是什么,我想展示。 55 00:02:59,200 --> 00:03:04,410 而这里输出的数量 我们已计算。 56 00:03:04,410 --> 00:03:06,800 >> 在这种情况下,我可能会 想知道准确 57 00:03:06,800 --> 00:03:11,380 发生了什么之前和 经过一些特定的计算。 58 00:03:11,380 --> 00:03:16,224 所以,我可能会使用前一个printf 与该行代码后。 59 00:03:16,224 --> 00:03:18,640 在这种情况下,我连 使其多一点点清晰 60 00:03:18,640 --> 00:03:21,960 通过之前说的调试 并经过调试等等 61 00:03:21,960 --> 00:03:26,540 我不混淆自己 多行看起来完全相同。 62 00:03:26,540 --> 00:03:32,290 >> 现在,如果我们重新编译这个和运行 它,再输入一个数字到五, 63 00:03:32,290 --> 00:03:35,090 我们可以看到,我们有 现在,前后输出 64 00:03:35,090 --> 00:03:40,670 并且发现,我们没有做明确的 数师或明确有 65 00:03:40,670 --> 00:03:43,680 我们真正想要做的。 66 00:03:43,680 --> 00:03:48,660 现在,在这种情况下,这是 不是一个真正的清晰输出。 67 00:03:48,660 --> 00:03:52,440 这不是一个真正的明确的结果是 我们想从这个特定的程序。 68 00:03:52,440 --> 00:03:54,427 >> 这是,再等 有点做作。 69 00:03:54,427 --> 00:03:57,510 但是,也许的事情之一 我们可以做,如果说明书说 70 00:03:57,510 --> 00:04:01,900 我们希望通过划分这 2,并添加1--所以换句话说, 71 00:04:01,900 --> 00:04:04,550 我们要舍up--然后 我们能知道我们能 72 00:04:04,550 --> 00:04:08,060 这样做特别的事情,在这种情况下。 73 00:04:08,060 --> 00:04:14,010 现在,在这里,我们知道,我们将 能加1到我们的一半数量。 74 00:04:14,010 --> 00:04:16,490 >> 让我们重新编译这个 并确认此 75 00:04:16,490 --> 00:04:18,860 行为是我们想要的方式。 76 00:04:18,860 --> 00:04:21,980 我们现在才看到, 有,我们有数字5。 77 00:04:21,980 --> 00:04:26,620 有后,我们有3号, 它根据我们的说明书中, 78 00:04:26,620 --> 00:04:29,292 就是我们想做的事。 79 00:04:29,292 --> 00:04:31,000 但是,如果我们看一下 输出这里,我们可以 80 00:04:31,000 --> 00:04:33,760 看到我们可能有另一个 完全错误,这是 81 00:04:33,760 --> 00:04:36,940 我们是从0开始计数了。 82 00:04:36,940 --> 00:04:39,390 >> 现在再次,这是一件 我们已经看到在过去 83 00:04:39,390 --> 00:04:42,500 我们可以很容易解决。 84 00:04:42,500 --> 00:04:44,790 但在这种情况下,我们 也有益处 85 00:04:44,790 --> 00:04:48,940 使用printf语句的 直接在for循环 86 00:04:48,940 --> 00:04:52,930 准确地知道在哪里 该错误发生。 87 00:04:52,930 --> 00:04:55,150 所以printf的声明 在帮助非常有用 88 00:04:55,150 --> 00:04:57,940 你确定, 正是在你的源代码, 89 00:04:57,940 --> 00:05:00,620 一个特定的错误发生。 90 00:05:00,620 --> 00:05:03,650 >> 而且这也是很重要的实现 如此,当我们在写代码, 91 00:05:03,650 --> 00:05:06,052 大家可能都假设 约的节目的状态。 92 00:05:06,052 --> 00:05:08,510 或者我们可能有假设 关于什么是计划的一部分 93 00:05:08,510 --> 00:05:13,020 实际上是正确或不正确时, 后来,我们建立在该程序 94 00:05:13,020 --> 00:05:15,950 并使其一部分 复杂的大型项目 95 00:05:15,950 --> 00:05:19,700 我们认识到,某些方面 那其实是马车。 96 00:05:19,700 --> 00:05:22,680 >> 用printf可以真正帮助 缩小并确定 97 00:05:22,680 --> 00:05:26,430 程序的区域可能不 要准确地行为的方式,我们 98 00:05:26,430 --> 00:05:29,500 预计,基于我们的假设。 99 00:05:29,500 --> 00:05:31,460 但是,还有其他工具 可用,还有, 100 00:05:31,460 --> 00:05:34,860 这使我们能够揣摩 出在哪里发生异常 101 00:05:34,860 --> 00:05:39,930 而且,具体而言,有什么事情 正在发生的程序里面。 102 00:05:39,930 --> 00:05:41,990 >> 因此,用printf非常 有用当我们要 103 00:05:41,990 --> 00:05:45,900 以确定的特定区域 一个程序,有一定的缺陷。 104 00:05:45,900 --> 00:05:47,730 但它也变得 一段时间后,乏味。 105 00:05:47,730 --> 00:05:50,500 在这种情况下,这是一个 比较简单的程序 106 00:05:50,500 --> 00:05:52,750 只有一个或两个变量。 107 00:05:52,750 --> 00:05:57,260 而且它变得非常容易让我们 打印出这些变量的值 108 00:05:57,260 --> 00:05:59,670 在较大的程序的情况下。 109 00:05:59,670 --> 00:06:02,670 >> 但是,我们可能有不同的 程序,有很多变数。 110 00:06:02,670 --> 00:06:06,530 并且它可能不是很 这么好用的printf 111 00:06:06,530 --> 00:06:10,120 尝试评估正在发生什么 对这些变量中的每一个 112 00:06:10,120 --> 00:06:13,590 作为上述程序的执行。 113 00:06:13,590 --> 00:06:16,960 有一个程序存在 所谓调试程序。 114 00:06:16,960 --> 00:06:20,320 在这种情况下,一个我们将 使用的是GNU调试器或GDB, 115 00:06:20,320 --> 00:06:24,260 这使我们能够检查内部 一个程序的在一个更运作 116 00:06:24,260 --> 00:06:25,700 详细方法。 117 00:06:25,700 --> 00:06:28,810 >> 事实上,我们可以执行 GDB的命令行 118 00:06:28,810 --> 00:06:35,370 在这里,只需键入GDB和 我们要调试命令。 119 00:06:35,370 --> 00:06:37,550 在这种情况下,指望。 120 00:06:37,550 --> 00:06:41,650 现在,在这种情况下,我们可以看到,它 给我们带来了一个提示GDB的说。 121 00:06:41,650 --> 00:06:44,020 而我们实际上可以 执行命令GDB 122 00:06:44,020 --> 00:06:48,260 实际开始执行的 计划,停止在某些点, 123 00:06:48,260 --> 00:06:51,060 评估的变量和 检查变量 124 00:06:51,060 --> 00:06:54,152 存在于程序状态 在该特定时刻, 125 00:06:54,152 --> 00:06:55,110 等,等等。 126 00:06:55,110 --> 00:06:57,240 它提供了大量的电力给我们。 127 00:06:57,240 --> 00:06:59,960 >> 但它只是恰巧 该CS50 IDE还 128 00:06:59,960 --> 00:07:05,870 提供了一个GUI或用户 接口GDB的 129 00:07:05,870 --> 00:07:11,120 使我们能够做到这一点,而无需 命令行界面任何 130 00:07:11,120 --> 00:07:13,560 或甚至全部。 131 00:07:13,560 --> 00:07:16,930 我可以访问的方法 是通过使用调试按钮 132 00:07:16,930 --> 00:07:20,120 在CS50 IDE的最顶端。 133 00:07:20,120 --> 00:07:24,280 现在,在过去,我们所拥有的 可见的是,我们使用命令 134 00:07:24,280 --> 00:07:27,660 行编译,然后运行程序。 135 00:07:27,660 --> 00:07:29,790 >> 调试按钮的功能 二者的那些步骤。 136 00:07:29,790 --> 00:07:34,380 但它也带来了 最右边的调试器选项卡 137 00:07:34,380 --> 00:07:38,280 这使我们能够检查各种 该方案的性能的 138 00:07:38,280 --> 00:07:40,500 因为它正在执行。 139 00:07:40,500 --> 00:07:44,280 如果我点击调试,在此 情况下,它会弹出 140 00:07:44,280 --> 00:07:48,230 在控制台中的新选项卡 窗口在最底层。 141 00:07:48,230 --> 00:07:51,160 >> 你可以看到这个选项卡 一些信息在最高层。 142 00:07:51,160 --> 00:07:52,670 我们可以在很大程度上忽略了这一点。 143 00:07:52,670 --> 00:07:54,800 不过的事情之一 我们要注意 144 00:07:54,800 --> 00:07:57,170 是,它输出 同样的事情,我们 145 00:07:57,170 --> 00:08:03,000 会得到,如果我们试图运行make在 C程序的终端窗口。 146 00:08:03,000 --> 00:08:06,230 >> 在这里,我们可以看到它的运行铛, 它有各种标志, 147 00:08:06,230 --> 00:08:12,660 并且它编译我们count.c文件, 这在当时所选标签 148 00:08:12,660 --> 00:08:15,100 我打的调试。 149 00:08:15,100 --> 00:08:18,010 因此,这是因为非常有用的 现在用这个调试按钮, 150 00:08:18,010 --> 00:08:23,280 我们可以同时编译,然后 执行程序,我们实际上 151 00:08:23,280 --> 00:08:24,460 要运行。 152 00:08:24,460 --> 00:08:27,880 >> 之一是标志 重要的是,在这种情况下, 153 00:08:27,880 --> 00:08:30,190 我们实际使用过 时间最长 154 00:08:30,190 --> 00:08:32,450 但也只是做了一些手 挥手[听不清],其中 155 00:08:32,450 --> 00:08:33,820 这是一个正确的位置。 156 00:08:33,820 --> 00:08:35,790 在铿锵,它说-ggdb3。 157 00:08:35,790 --> 00:08:38,570 158 00:08:38,570 --> 00:08:41,250 在这种情况下,我们都 告诉铛,我们的编译器, 159 00:08:41,250 --> 00:08:43,820 就是我们要编译我们的节目。 160 00:08:43,820 --> 00:08:46,810 但也提供了什么 所谓的符号信息 161 00:08:46,810 --> 00:08:50,940 从而使编译器实际访问 来了很多底层信息的 162 00:08:50,940 --> 00:08:52,610 包含在程序中。 163 00:08:52,610 --> 00:08:55,260 >> 更具体地,数 对我有作用, 164 00:08:55,260 --> 00:08:58,000 这些函数的名称, 变量,其种类 165 00:08:58,000 --> 00:09:01,730 这些变量是,和各种 其他的事情,帮助调试器 166 00:09:01,730 --> 00:09:04,350 执行它的操作。 167 00:09:04,350 --> 00:09:06,600 现在有别的东西 这是重要的提 168 00:09:06,600 --> 00:09:10,280 当我们讨论运行 一个程序以这种方式。 169 00:09:10,280 --> 00:09:13,660 >> 请注意,它实际上已经 提出了一个新的标签在我们的控制台 170 00:09:13,660 --> 00:09:14,780 沿底部。 171 00:09:14,780 --> 00:09:18,600 我们不再需要互动 直接与终端窗口。 172 00:09:18,600 --> 00:09:21,420 但这个新选项卡 实际上是一个终端窗口。 173 00:09:21,420 --> 00:09:26,710 它只是特定于运行 我们已经创建的程序。 174 00:09:26,710 --> 00:09:29,270 >> 注意,在底部,在 一些输出组合 175 00:09:29,270 --> 00:09:33,500 通过铛编译器和GDB, 我们可以在很大程度上忽略了, 176 00:09:33,500 --> 00:09:37,570 它实际上显示的输出 我们的节目在最底层。 177 00:09:37,570 --> 00:09:41,240 现在,实现重要 这一个窗口实际上 178 00:09:41,240 --> 00:09:43,360 会告诉你 从你的程序输出 179 00:09:43,360 --> 00:09:47,190 但也可以接受输入 该程序,也是如此。 180 00:09:47,190 --> 00:09:49,260 >> 因此,通知,上面写着 请输入一个数字, 181 00:09:49,260 --> 00:09:53,050 这是我们有相同的输出 曾在终端窗口前。 182 00:09:53,050 --> 00:09:55,510 但它现在在这个新的选项卡中显示。 183 00:09:55,510 --> 00:09:56,550 我可以输入一个数字。 184 00:09:56,550 --> 00:10:00,900 它实际上 如我们预期的功能 185 00:10:00,900 --> 00:10:05,890 向我们展示了我们的调试输出, 输出可能是越野车, 186 00:10:05,890 --> 00:10:07,010 正如我们之前看到的。 187 00:10:07,010 --> 00:10:10,460 而在最底层,它 实际上有一些额外的输出 188 00:10:10,460 --> 00:10:14,550 从GDP中只是说 这一计划已完成。 189 00:10:14,550 --> 00:10:16,655 >> 现在,当你在这个看到的 特别是贯穿, 190 00:10:16,655 --> 00:10:19,370 这是没有特别 有用的,因为即使是 191 00:10:19,370 --> 00:10:23,740 虽然我们已经调试器菜单来 起来,这仍然是一个正在运行的程序。 192 00:10:23,740 --> 00:10:26,790 在任何时候,它实际上 暂停执行对我们 193 00:10:26,790 --> 00:10:30,767 要能够检查所有的 内包含的变量。 194 00:10:30,767 --> 00:10:32,850 还有别的东西 我们必须做的,为了 195 00:10:32,850 --> 00:10:36,910 让GDB认识到,我们要 暂停程序的执行 196 00:10:36,910 --> 00:10:42,820 而不是只允许它继续 通常,我们会在任何其他情况下。 197 00:10:42,820 --> 00:10:45,530 >> 为了暂停执行, 在一些具体的线路, 198 00:10:45,530 --> 00:10:47,830 我们需要创建什么 叫一个破发点。 199 00:10:47,830 --> 00:10:52,670 而一个破发点很容易产生 在这CS50 IDE通过利用鼠标 200 00:10:52,670 --> 00:10:57,090 并直接点击向左 的一些具体的行号。 201 00:10:57,090 --> 00:10:59,920 一旦我做到这一点,一个红点 出现,这表明 202 00:10:59,920 --> 00:11:02,300 即该行现在是一个破发点。 203 00:11:02,300 --> 00:11:07,540 >> 而下一次我运行GDB,它 将在该断点停止执行 204 00:11:07,540 --> 00:11:10,280 当它到达该行代码。 205 00:11:10,280 --> 00:11:12,230 现在,这是一个重要的 事情来实现 206 00:11:12,230 --> 00:11:16,140 这并不一定是 情况下每行代码 207 00:11:16,140 --> 00:11:17,880 实际上是访问。 208 00:11:17,880 --> 00:11:23,780 如果我要创建一个函数 在这里,对于example--空F-- 209 00:11:23,780 --> 00:11:31,230 而只是做一个打印线这里 - 你好 天下 - 如果我从来没有调用这个函数, 210 00:11:31,230 --> 00:11:34,770 它会是这样的情况, 如果我在这里设置一个破发点, 211 00:11:34,770 --> 00:11:36,220 功能将永远不会被调用。 212 00:11:36,220 --> 00:11:38,310 因此,这 尤其是破发点 213 00:11:38,310 --> 00:11:43,040 将实际上从未暂停 程序的执行。 214 00:11:43,040 --> 00:11:48,020 >> 所以我们可以说,我正确地创建 在编写一些代码行一个破发点 215 00:11:48,020 --> 00:11:50,340 实际上将被执行。 216 00:11:50,340 --> 00:11:53,470 现在,在这种情况下,这是 在主函数中第一行。 217 00:11:53,470 --> 00:11:56,630 因此,这将肯定是这样的 即,只要我开始执行, 218 00:11:56,630 --> 00:11:58,580 在第一行必达。 219 00:11:58,580 --> 00:12:00,230 广发行将暂停执行。 220 00:12:00,230 --> 00:12:04,100 然后,我就可以 与调试器进行交互。 221 00:12:04,100 --> 00:12:08,480 >> 您可以设置多条线路为 断点,如果你想。 222 00:12:08,480 --> 00:12:11,365 我们也可以创建一个排队 在这里这段代码中 223 00:12:11,365 --> 00:12:12,490 永远不会到达。 224 00:12:12,490 --> 00:12:14,744 而且我们还可以设置一个另外的下面。 225 00:12:14,744 --> 00:12:16,660 究其原因,我们将 要做到这一点,我们将 226 00:12:16,660 --> 00:12:19,119 进入多一点点 详细一会儿就好了。 227 00:12:19,119 --> 00:12:21,660 所以现在,我只想禁用 这些额外的破发点 228 00:12:21,660 --> 00:12:24,940 这样我们就可以看看会发生什么 当我有一个单一的突破 229 00:12:24,940 --> 00:12:27,650 点在我的计划。 230 00:12:27,650 --> 00:12:29,410 我已经取得了一些 改变这一计划。 231 00:12:29,410 --> 00:12:30,750 所以,我要保存它。 232 00:12:30,750 --> 00:12:34,490 我会点击调试,这样我就可以 开始编译,然后 233 00:12:34,490 --> 00:12:36,880 执行调试器。 234 00:12:36,880 --> 00:12:40,632 >> 我们将看到,时刻,后 我们选择作为断线 235 00:12:40,632 --> 00:12:43,360 点以黄色突出显示。 236 00:12:43,360 --> 00:12:47,440 我们还可以看到,在 右上角的调试面板 237 00:12:47,440 --> 00:12:50,940 该暂停图标已经变成 进入一个小播放图标。 238 00:12:50,940 --> 00:12:54,710 这意味着,我们必须暂停 执行,在该特定情况下。 239 00:12:54,710 --> 00:12:57,840 而且打的播放按钮会 让我们继续执行 240 00:12:57,840 --> 00:13:00,000 在该特定的点。 241 00:13:00,000 --> 00:13:03,240 >> 请注意,还有几个其他的 在此调试面板可用按钮, 242 00:13:03,240 --> 00:13:04,220 为好。 243 00:13:04,220 --> 00:13:09,470 步过,这让我 执行该一行代码 244 00:13:09,470 --> 00:13:14,030 并加强了该行的 下一个,其中,在这种情况下, 245 00:13:14,030 --> 00:13:17,060 将意味着printf的 被执行的语句。 246 00:13:17,060 --> 00:13:22,310 它将然后暂停 执行第13行,像这样。 247 00:13:22,310 --> 00:13:25,090 >> 而且还有一个步骤 进入功能, 248 00:13:25,090 --> 00:13:28,950 如果我创建了其他非常有用 功能在源代码中其他地方。 249 00:13:28,950 --> 00:13:31,420 我想踏进 这些功能,而不是 250 00:13:31,420 --> 00:13:33,050 执行该功能为一体。 251 00:13:33,050 --> 00:13:37,279 但是,我们会看到更多的步骤 成在短短的一瞬间功能。 252 00:13:37,279 --> 00:13:40,320 现在注意到一些其他的东西, 此调试面板中实际存在。 253 00:13:40,320 --> 00:13:44,110 >> 我们有这个小组被称为 调用堆栈,它向我们展示了 254 00:13:44,110 --> 00:13:45,300 到底在哪我们。 255 00:13:45,300 --> 00:13:48,550 在这种情况下,我们都在里面 的主要功能。 256 00:13:48,550 --> 00:13:50,880 我们的脚本被称为count.c。 257 00:13:50,880 --> 00:13:53,820 而我们正好是在 线13,列中的一个,其 258 00:13:53,820 --> 00:13:58,950 正是高亮区域 的源代码指示,以及。 259 00:13:58,950 --> 00:14:02,435 >> 现在请注意,这也显示了 在局部变量节 260 00:14:02,435 --> 00:14:06,710 所有的变量是 这个函数中存在。 261 00:14:06,710 --> 00:14:08,930 要注意这一点很重要 所有的变量的 262 00:14:08,930 --> 00:14:12,580 将出现在这个局部变量 一个函数内部分, 263 00:14:12,580 --> 00:14:14,380 甚至在它们被定义。 264 00:14:14,380 --> 00:14:19,160 在这里我们可以看到,我们有一个变量 中名为num,拥有默认值为0, 265 00:14:19,160 --> 00:14:21,280 它是int类型的。 266 00:14:21,280 --> 00:14:24,110 >> 现在摆在我们实际初始化 所有这些变量, 267 00:14:24,110 --> 00:14:26,685 我们不一定 保证看到的值为0。 268 00:14:26,685 --> 00:14:29,200 和取决于其他处决 已执行 269 00:14:29,200 --> 00:14:32,020 和你的内存时的状态 你真正运行这个程序, 270 00:14:32,020 --> 00:14:34,605 你可能会发现你 看不到的0值 271 00:14:34,605 --> 00:14:36,550 和,相反,一些其它疯狂的数字。 272 00:14:36,550 --> 00:14:38,390 >> 但不要担心。 273 00:14:38,390 --> 00:14:44,610 它不会是相关的,直到 你居然初始化值。 274 00:14:44,610 --> 00:14:49,630 现在,在这种情况下,我们可以看到, 我已经进行了一些输出。 275 00:14:49,630 --> 00:14:52,131 而我,现在,暂停执行。 276 00:14:52,131 --> 00:14:53,880 但在这种情况下,什么 我真正想做的事情 277 00:14:53,880 --> 00:14:58,060 就是到现在跨过这条线 的代码,这样我实际上可以 278 00:14:58,060 --> 00:15:04,390 查询该INT用户的 我们希望在我们的程序中使用。 279 00:15:04,390 --> 00:15:07,060 >> 现在,在这种情况下,当 我打了一步,通知 280 00:15:07,060 --> 00:15:11,940 该暂停或者说恢复 按钮已更改为这个暂停按钮 281 00:15:11,940 --> 00:15:14,022 因为这段代码实际上执行。 282 00:15:14,022 --> 00:15:15,730 怎么了 现在的问题是,它是 283 00:15:15,730 --> 00:15:21,630 等待我们输入一些信息 因为我们可以通过我们的输出文本见 284 00:15:21,630 --> 00:15:23,600 在最底层。 285 00:15:23,600 --> 00:15:25,787 >> 所以,现在,这是 实际上没有暂停, 286 00:15:25,787 --> 00:15:28,620 即使它,排序,出现 是因为什么也没有发生。 287 00:15:28,620 --> 00:15:32,360 但它只是恰巧,在 我对13号线的具体情况, 288 00:15:32,360 --> 00:15:34,210 我在等待用户输入。 289 00:15:34,210 --> 00:15:39,130 所以GDB不能检查 一个程序,因为它正在运行。 290 00:15:39,130 --> 00:15:43,370 >> 现在,我进入了一些,下一次 input--所以我会输入数字5, 291 00:15:43,370 --> 00:15:46,140 正如我们所看到的 past--按回车,我们 292 00:15:46,140 --> 00:15:51,430 请注意,立即暂停GDB 并再次强调了下一行。 293 00:15:51,430 --> 00:15:55,320 但现在发现,作为 我们的输入值的结果, 294 00:15:55,320 --> 00:15:58,930 我们里面更新的价值 我们的局部变量,哪个 295 00:15:58,930 --> 00:16:05,560 为准确地知道非常有用 是什么数为在内存中。 296 00:16:05,560 --> 00:16:10,650 >> 现在,我可以允许此程序继续运行 玩到其执行结束 297 00:16:10,650 --> 00:16:12,570 击中恢复。 298 00:16:12,570 --> 00:16:16,410 我们可以看到,非常快 请问程序执行完毕 299 00:16:16,410 --> 00:16:19,790 具有相同的输出,我们 收到,调试器关闭, 300 00:16:19,790 --> 00:16:23,170 现在这个计划 完全停止。 301 00:16:23,170 --> 00:16:25,320 >> 我表明,只有在 用途看什么 302 00:16:25,320 --> 00:16:27,280 发生在我们居然打简历。 303 00:16:27,280 --> 00:16:30,640 但是实际上我们要 要返回到该程序 304 00:16:30,640 --> 00:16:33,820 这样我们就可以尝试调试 正是正在发生的事情。 305 00:16:33,820 --> 00:16:37,980 现在,我使用调试器,我可能 并不需要这些调试printf的语句。 306 00:16:37,980 --> 00:16:43,860 >> 所以,我可以将其删除,因为我会做 现在只是回到我们的简单的代码 307 00:16:43,860 --> 00:16:45,950 我们过会儿前。 308 00:16:45,950 --> 00:16:48,790 现在,当我保存 编程并执行它, 309 00:16:48,790 --> 00:16:53,700 它将再次进入初始 突破一点,我对11行。 310 00:16:53,700 --> 00:16:57,700 而我就可以检查 我的变量我想做的事情。 311 00:16:57,700 --> 00:17:00,695 >> 它只是恰巧,这 部分是不是很有趣, 312 00:17:00,695 --> 00:17:04,364 我知道,我要去 打印出这个声明。 313 00:17:04,364 --> 00:17:05,280 请输入一个数字。 314 00:17:05,280 --> 00:17:08,099 然后,我知道我要去 索要该整数用户。 315 00:17:08,099 --> 00:17:13,329 所以,或许,其实我是想动我的 向下突破点得远一点。 316 00:17:13,329 --> 00:17:16,710 >> 您可以删除断点 通过点击,再次,直接 317 00:17:16,710 --> 00:17:18,460 到的该行编号的左侧。 318 00:17:18,460 --> 00:17:22,200 这红点消失时表示 这是破发点现在已经没有了。 319 00:17:22,200 --> 00:17:24,780 现在,在这种情况下, 执行已暂停。 320 00:17:24,780 --> 00:17:27,770 所以它实际上没有打算 恢复在该特定实例。 321 00:17:27,770 --> 00:17:30,210 但是,我可以设置一个断点 在稍后一点。 322 00:17:30,210 --> 00:17:33,880 >> 当我现在恢复 代码,它会继续,并告诉 323 00:17:33,880 --> 00:17:36,190 如此地步,断点。 324 00:17:36,190 --> 00:17:37,374 同样,我打了简历。 325 00:17:37,374 --> 00:17:39,040 似乎不喜欢什么正在发生的事情。 326 00:17:39,040 --> 00:17:41,450 但是,这是因为我的 代码等待输入。 327 00:17:41,450 --> 00:17:47,900 我将进入5号,敲回车,和 现在,下一个断点将受到打击。 328 00:17:47,900 --> 00:17:50,570 >> 现在,在这种情况下,这 是代码行 329 00:17:50,570 --> 00:17:53,820 ,在此之前,我们就知道 正好是马车。 330 00:17:53,820 --> 00:17:57,590 因此,让我们评估发生了什么 在这一时代的特殊点。 331 00:17:57,590 --> 00:18:02,620 当行被突出显示,该 线尚未被执行。 332 00:18:02,620 --> 00:18:06,490 所以在这种情况下,我们可以看到 我有一个数字,它 333 00:18:06,490 --> 00:18:11,610 我有一个名为一个整数 NUM具有值为5。 334 00:18:11,610 --> 00:18:15,090 而我要表演 一些数学上的那个数字。 335 00:18:15,090 --> 00:18:20,130 >> 如果我跳过了,就可以 请注意,对于NUM值 336 00:18:20,130 --> 00:18:23,780 按照已经改变 算术,我们实际上已经完成。 337 00:18:23,780 --> 00:18:26,810 而现在,我们 这个循环里面 338 00:18:26,810 --> 00:18:29,090 还是现在的for循环 本身是突出, 339 00:18:29,090 --> 00:18:32,450 我们可以看到,我们有一个新的 变量调用我的 340 00:18:32,450 --> 00:18:35,370 将被用在该for循环。 341 00:18:35,370 --> 00:18:38,230 >> 我现在才记 提到,有时你 342 00:18:38,230 --> 00:18:43,470 会看到某种疯狂 数字作为默认该号码 343 00:18:43,470 --> 00:18:45,530 或者变量 实际上初始化。 344 00:18:45,530 --> 00:18:49,040 我们可以看到,正是 在这里的这个可变 345 00:18:49,040 --> 00:18:51,345 称为I,其具有不 尚未初始化 346 00:18:51,345 --> 00:18:53,560 在突出的时间。 347 00:18:53,560 --> 00:18:57,070 但是,我们可以看到,它有一定的数量 我们不会真正期望的。 348 00:18:57,070 --> 00:18:57,620 >> 没关系。 349 00:18:57,620 --> 00:18:59,661 别担心 因为我们有没有真正 350 00:18:59,661 --> 00:19:04,970 初始化的数量,直到我 跨过这条线与价值 351 00:19:04,970 --> 00:19:08,560 我已经被初始化为值1。 352 00:19:08,560 --> 00:19:11,400 所以一看就知道这其实 的情况下,让我们跳过。 353 00:19:11,400 --> 00:19:14,420 现在我们可以看到,这 线已经被执行。 354 00:19:14,420 --> 00:19:17,000 而我们现在强调 这个printf的线。 355 00:19:17,000 --> 00:19:22,230 >> 我们现在可以看到我们是如何价值观 i和3随时间而变化。 356 00:19:22,230 --> 00:19:26,450 这是非常有用的事,事实上, 是重复步过线。 357 00:19:26,450 --> 00:19:30,480 你可以找到真正是什么 碰巧你对循环内 358 00:19:30,480 --> 00:19:33,660 并会发生什么变化 变量内,对于环 359 00:19:33,660 --> 00:19:39,200 作为程序执行 发生一步一个脚印的时间。 360 00:19:39,200 --> 00:19:41,110 >> 现在,在这一点上,我 跨过刚好够用 361 00:19:41,110 --> 00:19:44,210 那我现在在我的程序结束。 362 00:19:44,210 --> 00:19:46,980 如果我跨过,它会 实际上停止执行 363 00:19:46,980 --> 00:19:48,860 正如我们已经看到在过去。 364 00:19:48,860 --> 00:19:52,110 让我重新启动此,再一次,所以 我可以点别的东西出来, 365 00:19:52,110 --> 00:19:53,320 为好。 366 00:19:53,320 --> 00:19:55,350 >> 在这种情况下,它是 现在问我,再次, 367 00:19:55,350 --> 00:19:57,100 为一个数字,其 我会再次进入。 368 00:19:57,100 --> 00:20:00,300 但是这一次,我会在进入 数量较多,使得循环 369 00:20:00,300 --> 00:20:02,540 将重复多次。 370 00:20:02,540 --> 00:20:06,090 在这种情况下,我要去 输入值11。 371 00:20:06,090 --> 00:20:08,390 >> 现在,再次因为我设置 在第15行一个破发点, 372 00:20:08,390 --> 00:20:10,490 它会高亮显示该行。 373 00:20:10,490 --> 00:20:12,980 我们可以看到,我们的 11号是正确的 374 00:20:12,980 --> 00:20:15,560 代表我们的局部变量。 375 00:20:15,560 --> 00:20:22,460 现在跨过这一点,我们可以 看着发生在我们的I值是什么 376 00:20:22,460 --> 00:20:25,680 当我们着手这里面的for循环。 377 00:20:25,680 --> 00:20:31,960 它被递增每次我们 达到了顶部循环。 378 00:20:31,960 --> 00:20:35,110 >> 现在,可能的事情之一 是有用的执行过程中做 379 00:20:35,110 --> 00:20:40,490 这一计划是对我来说,其实 改变变量中游看 380 00:20:40,490 --> 00:20:42,450 发生在我的计划是什么。 381 00:20:42,450 --> 00:20:46,540 在这种情况下,其实我可以 双击该值。 382 00:20:46,540 --> 00:20:48,040 请注意,它变成了文本字段。 383 00:20:48,040 --> 00:20:50,280 >> 现在我可以进入不同的 价值共 384 00:20:50,280 --> 00:20:55,700 怎么看我的程序的行为 当我改变了这一切变化。 385 00:20:55,700 --> 00:20:59,560 现在,在这种情况下,可变 我现在包含值10。 386 00:20:59,560 --> 00:21:02,810 但该计划仍是 在暂停执行。 387 00:21:02,810 --> 00:21:07,610 当我踏上了过来,我看到 我的价值,我输入为10, 388 00:21:07,610 --> 00:21:12,170 不大于num的值越大, 这立即引起了循环 389 00:21:12,170 --> 00:21:14,240 停止执行。 390 00:21:14,240 --> 00:21:16,210 >> 现在,这不是唯一的 你之所以会 391 00:21:16,210 --> 00:21:19,450 要修改的变量的地方。 392 00:21:19,450 --> 00:21:22,210 你可能真的想 尝试修改它, 393 00:21:22,210 --> 00:21:24,590 您可以继续 执行一个循环 394 00:21:24,590 --> 00:21:27,370 或者,让你可以修改 之前,一些价值 395 00:21:27,370 --> 00:21:32,630 达到某些特定的算术 你是要执行。 396 00:21:32,630 --> 00:21:36,210 >> 所以,现在,我们实际上改变 i的值作为程序执行, 397 00:21:36,210 --> 00:21:39,540 它造成的for循环退出 ,过早地因为突然之间,我 398 00:21:39,540 --> 00:21:42,770 正好是大于该值 NUM的,这意味着,对于循环 399 00:21:42,770 --> 00:21:45,410 不再需要被执行。 400 00:21:45,410 --> 00:21:48,780 此外,它正好是 情况下,我们改变了我的价值 401 00:21:48,780 --> 00:21:53,270 该行17强调的时候, 这是在时间点 402 00:21:53,270 --> 00:21:56,280 该循环执行 实际上正在评估。 403 00:21:56,280 --> 00:22:00,210 >> 如果我改变的价值 我在不同的线路,比如19, 404 00:22:00,210 --> 00:22:03,360 我们会看到不同的 问题是因为19行会 405 00:22:03,360 --> 00:22:08,310 循环之前已经执行 条件进行重新评估。 406 00:22:08,310 --> 00:22:11,900 现在,在这一点上,我再次, 在这个程序结束。 407 00:22:11,900 --> 00:22:15,707 我可以让这种情况继续 让我的程序自然退出。 408 00:22:15,707 --> 00:22:18,290 但有几件事情 这是很重要的带走 409 00:22:18,290 --> 00:22:19,960 从这个特定的讨论。 410 00:22:19,960 --> 00:22:22,490 您需要评估 你自己的假设 411 00:22:22,490 --> 00:22:24,710 有关如何代码应表现。 412 00:22:24,710 --> 00:22:28,220 任何时候你觉得有些片 你知道发生了代码工作, 413 00:22:28,220 --> 00:22:30,940 这可能是一个红旗去 回顾和评估,并确保 414 00:22:30,940 --> 00:22:33,470 你的假设 如何代码运行 415 00:22:33,470 --> 00:22:38,290 其实真到是怎么回事 表现在你的源代码。 416 00:22:38,290 --> 00:22:41,300 >> 但更要的一点是, 当我们使用调试器, 417 00:22:41,300 --> 00:22:43,920 你可以把断点 不同的代码行, 418 00:22:43,920 --> 00:22:48,110 这将导致调试器 暂停执行在每个那些行 419 00:22:48,110 --> 00:22:52,210 这样就可以评估 内存甚至改变它在的地方。 420 00:22:52,210 --> 00:22:55,630 再次,请记住,你可以 创建多个断点,这样你 421 00:22:55,630 --> 00:23:00,390 也可以继续执行,跳跃 以上代码的大部分, 422 00:23:00,390 --> 00:23:04,790 它会自动暂停 在下一个破发点。 423 00:23:04,790 --> 00:23:07,760 >> 实际上有更先进 调试器的特性,以及。 424 00:23:07,760 --> 00:23:10,170 但是,我们必须向您推荐 一些后续的视频 425 00:23:10,170 --> 00:23:14,090 要真正梳理出怎么样 使用这些特定的功能。 426 00:23:14,090 --> 00:23:15,990 现在,谢谢 非常适合观看。 427 00:23:15,990 --> 00:23:18,080 祝你好运调试。