DOUG LLOYD:好吧GDB。 究竟是什么? 所以GDB,它代表 对于GNU调试器, 是一个真正真棒工具,我们就可以 用它来帮助我们调试我们的节目, 或者找出事情 在我们的计划去错了。 GDB令人惊讶的是强大的,但 输出和交互与它 可以是一个有点神秘。 这通常是一个命令行工具, 它会向你扔了很多信息。 它可以一种很难 解析究竟发生了什么。 幸运的是,我们已经采取措施 要解决这个问题为您 你通过CS50工作。 如果您没有使用图形 调试器,我的同事丹 Armandarse发话了相当 视频中的一些有关这个 应该在这里 现在,你可能需要 使用这些命令行 工具与GDB工作。 如果你工作在CS50 IDE,你并不需要这样做。 但是,如果你不 在CS50 IDE中工作, 也许使用一个版本 CS50电器, 或其他Linux操作系统 系统GDB安装就可以了, 您可能需要使用 这些命令行工具。 而且因为你可能 要做到这一点,它的 有用的只是为了了解 GDB工作的命令行。 但同样,如果你 使用CS50 IDE,你 可以使用图形化调试器 内置于在IDE。 因此,要得到的东西去与 GDB,开始调试 的一个特定的过程 程序,所有你需要做的 类型是GDB跟随 由程序名称。 因此,举例来说,如果你的程序是 你好,你可以键入GDB打招呼。 当你这样做,你会 拉上了GDB的环境。 您提示会发生变化, 而不是被它通常 当你输入的东西是 在命令line-- LS, cd--所有典型的 Linux命令,你的提示 将变更为,也许事情 像括号GDB括号。 这是你的新的GDB提示,因为 你GDB的环境中。 一旦环境的内部, 有两个主要的命令 你可能会使用 按照以下顺序。 第一个是b,即 短暂的休息。 而你输入b后,您通常 键入一个函数的名称, 或者,如果你碰巧知道 围绕什么,行号 你的程序开始 表现得有点怪异, 你可以键入一行 一些有作为。 什么B,或者休息,不 是它可以让你的程序 运行,直到某一点, 的功能,即,名称 您指定或线 您指定的号码。 在这一点上,它 将冻结执行。 这是一个非常好的事情,因为 一旦执行已经被冻结, 你可以开始很慢 逐步执行程序。 通常情况下,如果你已经运行 你的程序,他们非常短。 通常情况下,你键入点斜线什么 你的程序的名称,敲回车, 之前,你可以眨眼,你 程序已经完成。 这不是一个真正的大量的时间去尝试 并找出什么错误。 因此,它真的能放缓的东西 下降设置一个破发点与B, 然后加紧研究。 然后,一旦你已经设置的断点 一点,就可以运行该程序。 如果您有任何 命令行参数, 在此指定他们,而不是当 您键入GDB的程序名。 您可以指定所有的命令行 通过采取R或运行参数, 然后任何命令行参数 你需要你的程序中。 还有一些其他的真 重要的和有用的命令 内生产总值的环境。 所以,让我迅速 去了其中的一些。 第一是n,这是短的下一个, 您可以键入的下一个替代N, 这两个会的工作。 而这仅仅是速记。 正如你可能已经得到了 习惯了,能够类型的东西 短一般是更好的。 而且它会做的是,它会 向前一步一个块的代码。 因此它会继续前进 直到一个函数调用。 然后,而不是 潜入该函数 而经历了这一切功能 代码,它只是具备的功能。 该函数将被调用。 它会做任何的工作。 它会返回一个值, 调用它的功能。 然后你就移动到 下一行调用函数的。 如果你想一步 函数的内部, 而不是仅仅有 它执行,特别是 如果你认为问题 可能在于该函数中, 你可以,当然,设置断点 点那个函数内。 或者,如果你已经在运行,你可以 使用s到一步向前一行代码。 因此,这将介入 并潜入功能, 而不是只具有执行 而在功能上继续 你是为了调试。 如果你想知道 一个变量的值, 您可以键入p或打印, 然后将变量名。 这将打印出来给你, GDB的环境的内部, 的变量的名称,即你 - 原谅我 - 的变量的值 您已经命名。 如果你想知道每一个的值 从那里局部变量访问 你现在在你的 程序,您可以键入信息当地人。 它比快很多 键入p和再不管, 列出了所有的 你知道存在变数。 您可以输入信息的当地人,并 将打印出你的一切。 接下来是BT,这是 短的回溯。 现在,一般地, 在CS50特别早, 你不会真的有机会 使用BT或回溯追踪, 因为你没有的功能 调用等功能。 你可能有主呼叫 功能,但是这可能是它。 你没有其他的功能 调用另一个函数,该函数 调用另一个函数,等等。 但随着你的程序得到更多的 复杂,并且特别 当你开始工作 递归,回溯追踪 可以让你真正有用的方法 那种得到一些上下文哪里 我在我的计划。 所以说,你写你的代码, 你知道,主调用一个函数 f,这个调用一个函数 克,它调用一个函数h。 因此,我们有几层 嵌套回事。 如果你是内 您的GDB的环境, 你知道你的内 h的,但你忘了 关于什么让你到你 are--您可以键入BT或回溯追踪, 它会打印出H,G,F为主, 沿着一些其它的信息,这 为您提供了一个线索,确定主 所谓的F,F称为G,G称为H, 而这也正是我 目前我在我的计划。 因此,它可以是真正有用的, 尤其是在神秘的烦躁GDB的 变得有点势不可挡,以 找出到底是那里的东西。 最后,当你的程序完成后, 或者当你完成调试它 并且要一步之遥 从GDB的环境, 它有助于了解如何摆脱它。 您可以键入q,或退出,让出。 现在,今天的视频前 我准备了一个错误的程序 所谓buggy1,这是我编 从被称为buggy1.c一个文件。 如你所料,此 节目其实是在马车。 不顺心的事 当我尝试并运行它。 现在,不幸的是,我无意间 删除了我的buggy1.c文件, 所以为了让我弄清楚 什么错这个程序, 我将不得不使用 GDB那种盲目的,想 浏览该程序 弄清楚到底发生了什么错误。 但仅使用工具 我们已经了解了, 我们几乎可以图 出它到底是什么。 因此,让我们头以上 CS50 IDE,看一看。 好了,我们在这里在我 CS50 IDE环境, 我会放大一点点 所以你可以看到多一点。 在我的终端窗口中,如果我列出 我的现任董事的内容 使用ls,我们会看到,我 有几个源文件 这里,包括 前面讨论buggy1。 究竟推移,当 我尝试运行buggy1。 那么让我们来了解一下。 I型点斜线, 越野车,和我打回车键。 段故障。 这不好。 如果你还记得,一 段错误通常 当我们访问内存时 我们正在不许碰。 我们已经在某种程度上达成 的范围之外 什么样的程序,在 编译器,给了我们。 因此已经,这是一个 线索保持在工具箱中 当我们开始调试过程。 一些曾在这里得有点不对。 好吧,让我们开始 了GDB环境 看看我们是否能想出 究竟是什么问题。 我要明确我的屏幕, 我要去键入GDB 再次,进入GDB的环境, 和节目的名称 我想调试,buggy1。 我们得到一点消息,读 从buggy1符号,完成。 所有这一切意味着它拉 同时所有的代码, 而现在它已经装入 GDB,它已经准备好去。 现在,我想干什么? 你还记得什么 第一个步骤通常是 我这个环境里面之后? 但愿你说的设置 一个破发点,因为 其实这就是我想做的事情。 现在,我没有 这个源代码 在我的面前,这可能是 不是典型的用例,顺便说一句。 你可能会。 所以这是很好的。 但是,假设你不这样做,有什么 一个功能,你知道 在每一个C程序的存在? 无论多么大或多么复杂 它是,该功能肯定存在。 主,对不对? 所以没有一切,我们可以 设置在主一个破发点。 再次,我可以只输入 打破代替b为主。 如果你很好奇,如果你 曾经键入了一个长的命令 然后意识到,你 输入了错误的事情, 你想摆脱 一切正如我刚才那样, 你可以采取控制U,这将 删除一切,带给你回来 到光标线的开头。 快了很多不仅仅是按住 删除或打它一帮倍 过来。 因此,我们将设置一个破发点,在主。 正如你所看到的,它说我们已经 设置一个断点在文件buggy1.c, 显然在第一线 的主要代码行七人。 再次,我们没有 这里源文件, 但我认为这是 告诉我真相。 然后,我只是想 并运行程序,河 启动程序。 好了,所以这条消息 是有点神秘。 但基本上什么 发生在这里它只是 告诉我,我已经打了我突破 点,断点1号。 然后,该代码行, 没有这样的文件或目录。 唯一的原因, 我看到这个信息 是因为我无意中 删除了我的buggy.c文件。 如果我的buggy1.c文件存在 在当前的目录中, 该行那里实际上 告诉我的代码行 从字面上读。 不幸的是,我将其删除。 我们将不得不样的导航 通过这个有点盲目。 好了,让我们来看看,有什么 我想在这里做? 好吧,我想知道是什么地方 变量可能是提供给我。 我开始了我的计划。 让我们来看看可能是什么 已经初始化我们。 I型信息当地人,没有本地人。 好吧,使之不 给我一吨的信息。 我可以尝试,并打印出一个变量, 但我不知道任何变量名。 我可以尝试一回痕迹, 但我的主内, 所以我知道我没有作 另一个函数调用现在。 所以看起来像我的唯一选项 使用N或左右,开始潜水研究。 我会用了N。 所以我N型。 噢,我的天哪,这里究竟是怎么回事。 程序接收到的信号, SIGSEGV段故障, 然后一大堆东西。 我已经不堪重负。 嗯,实际上是一个 很多问题需要了解。 那么,这告诉我们什么? 它告诉我们的是,这个计划是 约而至,但还没有,赛格故障。 特别是,我要去 放大甚至进一步这里, 它是关于赛格故障有关 所谓的strcmp。 现在,我们可能还没有讨论 这一功能广泛。 但is--,因为我们不打算 说说每个功能 存在于C标准library-- 但他们都提供给你, 特别是如果你把一个 看reference.cs50.net。 而STRCMP是一个真正强大 功能存在内 该文件string.h头的 文件,这是一个标头 专用于功能的文件 与工作和处理字符串。 特别是,是什么的strcmp确实是 它比较两个字符串的值。 所以我要段错误 在通话中对strcmp好像。 我打了N,而事实上我得到的消息, 方案终止信号SIGSEGV 段故障。所以,现在 其实,我赛格故障, 而我的方案有相当 很多有效的放弃。 这是程序的结束。 它打破了,它坠毁。 所以,是不是很多,但我 实际上确实学到了不少 从这一点经验。 我学到了? 好了,我的程序崩溃 立刻漂亮多了。 我的程序崩溃的 一个打电话给strcmp,但我 没有在任何局部变量我 计划在它崩溃的时间。 那么,什么串,或字符串, 可能我可能会比较。 如果我没有任何地方 变量,你可能 推测,我have--有可能是一个 全局变量,这可能是正确的。 但总体来说,这似乎 像我比较 到不存在的东西。 因此,让我们探讨 一个远一点。 所以,我要明确我的屏幕。 我要离开了的 GDB环境一秒钟。 而且我想,OK,所以有 没有局部变量,在我的计划。 我不知道,也许我应该传球 在一个字符串作为命令行参数。 因此,让我们只是测试了这一点。 我以前没有这样做过。 让我们来看看,也许,如果我运行这个程序 使用命令行参数它的工作原理。 呵呵,不分段错误存在。 它只是告诉我,我想它了。 所以,也许这就是固定在这里。 事实上,如果我回去看看 对于buggy1.c实际的源代码, 它好像我在做什么是 我在做一个呼叫而不对strcmp 检查是否实际上的argv [1]存在。 这实际上是 源代码buggy1.c。 所以我真的需要 在这里做修复我的程序, 假设我有 在我面前的文件,是 只需添加一个检查,以 确保的argc等于2。 所以这个例子中,再次,就像我说的, 是有点做作,对吧? 你一般都不会去 不小心删除你的源代码 然后还要尝试 和调试程序。 但我们希望,它给了 您的说明 这样的东西那 你可能会想 为你调试程序。 什么是事务在这里的状态呢? 什么变量做我 有接近我? 具体在哪里我的计划 崩溃,在哪一行, 什么调用什么功能? 什么样的线索,这是否能给我吗? 而这也正是 一种心态,你 应该进入,当你 想着调试程序。 我是道格·劳埃德。 这是CS50。