[音乐播放] DAVID J.马兰所有权利。 [笑] 欢迎回来。 这是CS50。 而本周五结束。 到现在为止,我们已经差不多 被理所当然地认为有 存在这个编译器,铛,你 被调用的方式,此 其他工具叫,不知怎的, 神奇地转换你的源代码 成目标代码,零和一 您的电脑CPU,中央 处理单元,真正理解。 但事实证明,这是一个数字 在引擎盖下 输入和输出之间。 我想建议,我们的肉体 说出来的更详细一点成 这四个步骤,有一些所谓 前处理,这 被称为编译,我们已经看到, 一些所谓的组装, 一种叫做连接。 所以到现在为止,在我们的一些 计划,我们已经包含尖锐。 最近,我们已经有一些尖锐的 定义常量。 所以,事实证明,那些东西, 哈希符号或前缀 英镑符号是预处理器 指令。 这只是说这是一个奇特的方式 这实际上一行代码 转换成别的东西之前 电脑甚至尝试转换 成0和1的程序。 例如,夏普包括标准 I / O,H,非常简单,只是表示去 未来,抢的文件内容 STDIO.H并粘贴他们的权利有。 因此,没有零和一 但在这一点上。 这真的只是一个替代。 这样做了,在所谓的 预处理阶段,当你 实际运行锵或专门 在大多数情况下,制作。 所以这一切已经发生 首先自动迄今。 然后编译步骤。 但是,我们一直过于简单化 编译。 编译程序的真正含义 把它从像C的东西, 源代码中,我们一直都在写,同比下降 一种叫做组装。 汇编语言是一个较低的水平 语言,令人欣慰的是,我们不会 有很多借势 写这个学期。 但它的最低水平 某种意义上说,你从字面上开始写 加法和减法,乘法和加载 从内存中保存到内存中, 非常基本的指令,一台电脑, 引擎盖下, 其实理解。 最后,组装需要语言 零和的,我们已经 迄今为止描述。 最后,真正有所谓 链接阶段,我们将 看到在短短的时刻,它结合了 您的零和一零 其他的人之前 你已经创建。 所以考虑这个超级简单的程序。 它是从第1周。 它只是说,你好世界, 在屏幕上。 我们跑通过锵。 或者我们跑了,它通过使 跑锵。 和输出在当时 一些零和一。 但事实证明,有 一个中间步骤。 如果我在这里 - 哎呀,没 希望看到他呢。 如果我在这里,我的设备 我打开hello.c的,在这里 是相同的程序。 什么,我要做的事情在我的终端 窗口在这里我要 运行铛,而不是品牌, 自动完成所有四个 我们这些步骤。 我打算做铛-S 然后hello.c的,然后回车。 我得到一个闪烁提示 再次,这是很好的。 现在稍大一点的窗口, 我要打开的gedit这里。 我要打开的文件, 事实证明,被称为hello.s 包含该汇编语言 我前面提到的。 这是什么所谓的装配 语言,相当低的水平 英特尔CPU的指令, 或不管它是什么,里面 理解。 和MOV举动。呼叫是 调用,非常低的水平的功能。 子的减法。 所以当你有一个特定的CPU里面 你的电脑,是什么使得它 层次分明,与其它CPU上 市场,指示 理解,往往它的效率有多高 有多快,它是在执行某些 这些指令。 现在更多,你可以采取 明年秋季在大学CS61。 但在这里,我们有,例如,几 标识符可能看起来很熟悉。 hello.c的程序的名称。 文本 - 。 有没有更多的兴趣 刚才,记得该文本 段,截至周一,是在 内存的程序实际上结束了。 所以,这至少隐约 有熟悉。 在这里,当然,一提 我们的主要功能。 向下滚动,这是指对事物 所谓的寄存器,非常小块 您的实际CPU的内存里面。 如果我什至向下滚动 进一步,我看到某种 间接提及ASCII。 还有,的确是字符串, 你好,逗号,世界。 所以长话短说,这一直是 发生自动为您 在发动机罩下方的这段时间。 什么已经发生,真的是一次 你运行铛,或以 让你得到第一, 从源代码, 所谓的汇编语言。 然后锵转换组件 下降到零和的语言。 这是我们开始的幻灯片 我们讨论周0 - 然后1周。 最后,那些零和一 相结合,与零和一 这些库中,我们一直在服用 标准I / O或理所当然的像 字符串库,甚至 的CS50库。 所以画这幅画 在视觉上,我们有hello.c的。 而且,当然,使用了printf 功能说,你好世界。 编译步骤下来 该文件,我们刚才看到hello.s,甚至 虽然这通常将删除 自动为您。 但是,这是在汇编代码 在中间步骤。 那么当我们组装的组件 语言,可以这么说,这就是当你 得到这些零和一。 因此,我们今天有效放大 我们一直理所当然, 意味着源代码 反对代码。 但最后,现在相同的画面 - 让我们推到 左手侧。 并注意在上方有 我前面提到stdio.h中。 这是一个文件,我们已经包括了 在几乎所有的 我们写的程序。 的文件,其内容 获得复制粘贴, 有效之上代码。 但事实证明,在计算机上 系统某处,那里想必 有人写道多年stdio.c文件 以前,实现了所有的 被宣布功能 在stdio.h。 现在,在现实中它可能不上 您的Mac或PC或者甚至在 CS50设备是一个原始的C代码。 有人已经编译并计入 o文件对象代码或一个 文件,它指的是一个共享库 这已预装和 预编译的为您服务。 但是,假如确实存在 上我们的电脑stdio.c的并行 铛。 你的代码被编译 和组装。 stdio.c代码被编译和 组装,以便将该最后 一步,在这里,我们必须以某种方式 链接,可以这么说,你的零和一 用他或她的零和一成一体 简单的程序,最终是 调用你好。 所以这是所有魔法 发生迄今。 并会继续采取这些 过程是理所当然的,但实现 有很多有趣的细节 下方有。 这是什么使你 电脑与英特尔里面 特别显着。 因此,关于这一点,如果你想 我们一起吃午饭这个星期五,做 到一般地方cs50.net/rsvp, 周五下午1:15。 而现在的几个公告。 因此,我们有一些好消息。 我们有一些坏消息。 开始这里有一些好消息。 [呻吟] 好的。 嗯,这是技术上的一个假期,所以 它没有这么多我们的礼物。 但随后的坏消息,当然。 [呻吟] 我花了很多的时间 这些动画。 [笑] 会有一个审查会议 下星期一。 这将是下午5:30。 所有这些细节,我们会提醒你 通过电子邮件在球场上的 网站在短短两天时间。 将被拍摄下来,并提供 此后不久。 所以,如果你不能让周一 夜间插槽,不用担心。 第接下来的一周也将 专注于审查测验。 如果你的部分是,这是在周一 确实是大学的假期,我们将 仍然满足部分。 如果你根本无法使该 因为你会一节 离开,这很好。 出席星期日或周二部分或 调贾森的部分,这是 网上提供。 所以,更多的坏消息。 因此,根据教学大纲, 我们有讲座将于下周五。 但好消息 - 清楚,我花了太多时间。 [笑] 我们将在下周五的讲座取消。 所以这将是一个为我们的礼物,所以你 真的可以有一个很好的喘息 这个星期,两个星期,因此之间。 因此,没有讲座下周,只是一个很小的 小测验,你应该 越来越兴奋。 现在让我们把注意力转向 东西确实是更多的视觉 更加精彩和设置阶段 这是怎么回事,在地平线上 在短短的几个星期的时间。 第一次测验后,我们将把 关注我们的问题集 特定领域的问题,即 取证或安全性比较一般。 事实上,这个问题的传统 集对我来说是一个 教学资深会员​​或CAS走过 校园采取一些照片 可识别的,但无明显的人, 地方或事物,那么每年我 设法不小心删除 或破坏数字媒体卡 这是我们的相机内。 但没什么大不了的。 我可以继续前进,堵塞 进入我的电脑。 我可以做一个法医形象,所以 说话,复制零 该内存卡的,不论是 其SD卡或紧凑型闪存卡或 无论你是熟悉的。 然后我们就可以到手了。 因此,挑战未来,除其他 你的东西,是写 恢复了一大堆的C代码, 我的JPEG文件,并透露将 那些人,地方或事物。 而且我们还说话,在这个问题上 设置,并在未来的日子里,约 更普遍的图形。 我们已经使用,当然, 打破了。 不过,你那种理所当然的 存在这些高层概念 矩形和椭圆形。 但引擎盖下 有像素。 你不得不开始 想着这些。 或者你将P-集合4不得不思考 砖之间的差距,如何 很快,你的球跨越 在屏幕打出来。 所以有这样的概念 在屏幕上,这点 已经开始发挥作用。 现在你所看到的,不过,是什么 你在电脑屏幕上。 如果你曾经看过一些好的或 坏电视,赔率是他们几乎 对待观众喜欢科技进步 谁真的不 知道很多关于计算。 因此,它很容易为​​警察 侦探说,你能不能 清理一下我吗? 或加强,对不对? Enhance是一样的时髦词语 任何犯罪行为最相关的节目。 而现实的情况是,如果你把一个非常 犯罪嫌疑人在做的模糊照片 坏的东西,你不能 只是增强。 你不能无限放大。 你不能看到有人在闪烁 谁犯的眼 特别是犯罪,尽管 患病率在电视上。 因此,让的激励 一窥即将到来的设置问题 一些演出与您 可能是熟悉的。 [视频回放] - 确定。 现在,让我们好好看看你。 保持它。 执行回来。 等待一分钟。 向右走。 有。 冻结。 全屏。 - 确定。 冻结。 收紧,好吗? 在那家伙的矢量 由后轮。 放大在这里,在这一点上。 有了合适的设备,成像 可扩大和激化。 - 那是什么? 这是一个提升计划。 你能清除的任何? 我不知道。 让的增强。 增强第A-6。 我增强了细节和 - 我认为有足够的提升。 它释放到我的屏幕。 增强反映在她的眼睛。 让我们运行这个通过 视频增强。 埃德加,你可以加强这方面呢? 杭。 - 我一直在这种反射。 有人的反思。 反思。 - 有一个反射 男人的脸。 - 反思。 有一种体现。 放大上镜。 你可以看到的一种体现。 你能提升形象,从这里开始? 你能提高他在这里? 你能提高呢? 你能提高呢? 我们可以加强这方面呢? 你能提高呢? 保持一秒钟,我会提高。 - 放大在门上。 - X10。 变焦。 [笑] 移动英寸 等待,停止。 - 停止。 暂停。 旋转75度左右 的立式请。 [笑] 停止,和背部的部分 门再次。 得到的图像增强 ,位图? 也许我们可以使用普拉迪普森 进入windows的方法。 这个软件是最先进的。 的图标值是关闭的。 有了正确的组合 的算法。 他采取光照算法 一个新的水平,我可以用它们来 增强这张照片。 锁和放大的z​​轴。 - 增强。 - 增强。 - 增强。 冻结和提高。 [END视频播放] DAVID J.马兰:所以习题集 5是有什么样的未来。 所以,我们很快就会得到一个更好的理解 的时候,为什么你可以 我们不能以这种方式提高。 但首先,让我们回到我们的注意力 一些积木,我们会 需要能够讲这个故事。 所以记得我们画了这幅画上 周一有点上周。 描述事物的布局 在您的计算机的内存中时, 运行某些程序。 高科技板块向上顶,召回,是指 实际的零和一 构成你的程序。 有,下面,一些初始化或 未初始化的数据,这通常 指的东西像常量或 字符串或全局变量 事先声明。 还有的堆,但我们还会回来 回到那个在一个位。 再有就是在堆栈中。 很像一个托盘堆叠在 食堂,这就是内存得到 分层和分层时, 你做什么程序? 堆栈的使用是什么? 是吗? 调用的函数。 任何时候当你调用一个函数,它 其内存条子给 局部变量或参数。 形象,我们看到,每个 连续的函数调用,当A 调用B调用C调用D, 分层压入堆栈。 和在每个这些片 存储器本质上是一个独特的范围 该功能,当然 是有问题的,如果你想把手上 从一个函数另一块 你想让它的数据 到突变或更改。 那么,是什么使我们的解决方案 函数代表一个堆栈 帧改变内存里面 另一个堆栈帧呢? 怎么做这两彼此交谈? 因此,通过指针或地址, 再次,只是描述的 存储器,通过一个特定的 咬入号码“,特别是 价值,可以发现。 所以,记得最后一次,我们也继续 的故事,看了一眼 相当错误的程序。 这项计划是几车 的原因,但最令人担忧的是 因为它无法检查什么? 是啊,这不检查输入。 对不起? 如果超过12个字符。 所以非常巧妙,当调用存储器复制, 其中,顾名思义,就是 将存储器从它的第二个参数 进入它的第一个参数。 第三个参数,非常巧妙, 检查以确保你不 复制多个,在这种情况下,长度 酒吧的字符数, 到目标,这也是本 阵列C.但问题是什么 如果C本身不够大 处理这个问题? 你要复制的数量 你已经字节。 可是你实际上有更多的 字节比你有房吗? 那么,这个程序非常愚蠢只是 盲目继续采取一切它 ,你好反斜线0 伟大的,如果字符串是短 够了,像5个字符。 但是,如果它实际上是12个字符 1,200个字符,我们看到了最后一次 ,你只是要完全 覆盖内存, 不属于你。 而最坏的情况下,如果覆盖 红色的部分,我们叫做 返回地址 - 这仅仅是其中计算机 自动为你,后面的 场景,塔克斯走了32位值, 它提醒了什么地址,它应该 返回时富,其他功能, 完成执行。 这是一个各种各样的面包屑 它返回。 如果覆盖潜在的, 如果你是坏人,可以 潜在的接管 别人的电脑。 你肯定 在大多数情况下崩溃。 现在,这个问题只会加剧 当我们开始谈论内存 更普遍的管理。 和malloc内存分配,是一种 我们可以用它来分配的功能, 内存时,我们事先不知道 我们可能需要一些。 因此,举例来说,如果我回去 这里器具。 而且我打开从最后一次hello2.c, 记得这个节目在这里,看着 像这样一个小东西, 短短三行 - 说出你的名字,然后字符串名称, 在左边,等于的GetString。 然后,我们把它打印出来, 该用户的名称。 因此,这是一个超级简单的程序。 要清楚,让我继续前进 ,并招呼-2。 我打算做点斜线HELLO-2。 说出你的名字 - 大卫。 回车键。 你好,戴维。 它似乎确定工作。 但是,什么是真的 这里引擎盖下方? 首先,让我们剥开一些层。 字符串只是一个代名词,我们已经 实现了什么? 字符明星。 因此,让我们让它多了几分神秘的 但更多的技术上是正确的,这 是一个char星级,这意味着 名字,没错,就是一个变量。 但什么名字店的地址是 一个字符,这感觉有点怪 因为我得到一个字符串。 我得到多个 字符不是一个字符。 不过,当然,你只需要第一 字符的地址记住 整个字符串是因为什么原因呢? 你怎么找出其中的结束 字符串是知道的开始? 的反斜线零。 因此,这两条线索,你弄清楚 开始前和结束 任何字符串,只要他们 正确形成与空 终结者,,反斜线零。 但是,这是调用的getString。 事实证明的getString 这一切的时候已经种 欺骗我们。 它一直在做这种劳动,可以肯定, 得到了来自用户的字符串。 但该内存 被来自哪里? 如果我们回到这里的图片 从仅仅是一种应用的定义 刚才,堆栈 内存去当函数被调用时, 通过这种逻辑,当你需要调用getString 然后我输入 D-A-V-I-D输入,是D-A-V-I-D 反斜杠零存储的基础上, 我们的故事告诉我们多远? 这似乎是在 堆栈,对不对? 当你调用得到的字符串,你会得到一个 小片内存堆栈。 所以,按理说为D-A-V-I-D 反斜杠零被存储 在堆栈中。 但是且慢,形式返回 这个字符串,可以这么说,这意味着 它的托盘从食堂 堆栈。 和我们说最后一次,只要一 函数返回时,和你拿 托盘,可以这么说,从堆栈什么 你可以假设一下残存的 该内存? 我有点重划为问号 因为他们有效地成为 未知的值。 它们可以被重用,当一些 下一个函数被调用。 换句话说,如果我们碰巧 存储 - 我会画一个快速的图片 这里的堆栈。 如果我们碰巧绘制底部 我的内存段,我们会说 这是内存的地方 由主要可能ARG c和占用 ARG v和别的程序, 被称为的GetString时, 想必得到的getString 这里的内存块。 D-A-V-I-D不知何故 在这个函数中结束了。 我要简单化。 但是,让我们假设,其D-A-V-I-D 反斜杠零。 因此,这多少字节用于 GetString的框架。 但只要我们的形式返回, 说最后一次,这个内存超过 在这里,一切都变得 - 哟嗬! - 一切都变得有效擦除。 我们可以认为现在问题 标记,因为谁知道 这是怎么回事,成为该内存。 事实上,我经常调用函数 以外的getString。 而只要我调用其他一些 功能比的getString,也许不是在 我们刚刚看到这个特定程序 但一些其他的,当然其他一些 功能可能最终被定 这个堆栈中的下一个景点。 所以它不能说的GetString商店 D-A-V-I-D,因为我会在栈上 立即失去对它的访问。 但我们知道他们的GetString 只返回什么? 它不回国 我六个字符。 什么是真正回到根本 我们结束最后一次吗? 地址的第一人。 不知何故,当你打电话的GetString, 它分配的内存块 字符串的用户类型和 然后它返回地址。 事实证明,当你想 在这个函数来分配内存 人谁打电话的方式和回报 该函数的地址 该内存块,你绝对 不能把它在堆栈上 底部,因为在功能上它只是 会不会成为你很 很快,所以你大概可以猜测 我们可能会折腾 相反,所谓的堆。 因此,你的记忆的底部之间 布局和你的内存的顶部 布局段一大堆。 一个是堆栈,和右 它上面的堆。 和堆仅仅是一个不同的块 功能不用于内存 当他们调用。 它用于较长期的内存,当 你想一个函数来获取一些 内存,能够挂到 而失去控制权。 现在,你也许可以立即 看看,这是不是 不一定是完美的设计。 当你的程序分配的内存 栈,或如你所说 更多的功能,或作为您分配 用malloc销为堆内存 GetString的是做什么,清楚 似乎是不可避免的问题? 右。 喜欢的事实,这些箭头 指向对方 并不是一个好兆头。 事实上,我们可以非常迅速地崩溃 任何数目的方式中的程序。 事实上,我认为我们可能有 这样做一次意外。 如果没有,让我们做吧 现在故意。 让我继续前进,超快速 了一项名为dontdothis.c。 我现在就在这里和 不锋利包括stdio.h中。 声明函数foo需要 没有参数​​,这是 好记为无效。 foo的是要干什么,唯一 调用foo,这可能是不 最聪明的想法,但就这样吧。 耳鼻喉科主无效。 现在唯一的事情主要是去 要做的就是调用foo。 只是踢,我要去 提前这里说的printf“你好从 富。“ 确定。 所以,如果我没有犯任何错误, 请点斜线dontdothis。 让我们做一个更大的窗口 - 点斜线,dontdothis。 来吧。 嗯哦。 显然,你可以做到这一点。 该死的。 确定。 等待。 待机。 难道我们 - 我们没有使用它制作。 [叹息] 我知道,但我想我们 刚删除。 嗯,是啊。 该死的。 解决这个罗布。 什么? 这是非常简单的。 是啊,我们转向优化。 OK,站在再见。 现在我感觉好多了。 确定。 好的。 因此,让我们的编译 - 让你dontdothis。 您可能需要重命名为 只是一瞬间dothis.c。 我们去那里。 谢谢。 确定。 因此,事实上,我在打印 出来的东西实际上只是 放缓的过程,我们 已经达到了这一点。 确定。 唷! 所以实际上是什么回事呢? 之所以有,只是作为一个一边, 做任何输入 输出往往要慢一些,因为你 写入字符 屏幕,滚动。 所以长话短说,其实我 发生等的不耐烦了,我们将不得不 看到这个最终的结果也是如此。 现在,我得到了乘坐的打印, 我们看到它的时候了。 那么,为什么会出现这种情况。 好吧,简单的解释,当然, 可能是,富不应该 可以调用本身。 现在笼统, 这是递归。 我们想了几个星期 前递归是好的。 递归是这个神奇的方式 表达自己的超简洁。 它只是工作。 但有一个关键的功能,所有的 我们已经讨论过的递归程序 因此,看着远, 是他们有什么? 一个基本的情况,这是一些硬编码 情况下,在某些情况下,所述 不叫富,这显然是 不是这里的情况。 那么,什么是真正发生的事情 在这幅画吗? 那么,当主调用foo, 得到的片的内存。 当foo调用foo,它就会 一个切片的内存。 foo的调用foo时,它就会一片。 它得到一个切片。 它得到一个切片。 因为foo是永远不会回来了。 我们从来没有删除其中的一个 从堆栈帧。 所以,我们正在吹遍堆,而不是 何况谁知道还有什么, 我们正在超越我们的边界 所谓的内存段。 错误去分割假。 因此,解决办法是 显然没有做到这一点。 但是,更大的意义是,是的, 绝对是有一定的限制, 即使它没有很好的定义,至于如何 很多功能,你可以调用一个 程序,多少次的函数 可以调用本身。 因此,即使我们做了宣讲递归 作为这种潜在的神奇的东西一 几周前西格玛 功能,当我们得到的数据 结构和CS50,你会看到其他 它的应用,它不是 不一定是最好的事情。 因为如果一个函数调用本身, 调用本身,即使有基地 情况下,如果你不打,基本情况 1000电话或10000电话, 那个时候,你可能已经运行的空间 你所谓的堆栈和命中 一些其他的内存段。 所以它也是一种设计权衡 优雅和之间 您的特定的鲁棒性 实现。 所以还有另一个缺点或 另一个,这是我们的疑难杂症 一直在做迄今。 当我打电话的GetString - 让我回去到2个招呼。 请注意,我调用的getString 这是返回地址。 我们要求今天地址 是从堆中。 而现在,我打印出 在该地址的字符串。 但是,我们从来没有所谓的 相反的getString。 我们从来没有calll这样的函数 ungetstring,在那里你的手背 该内存。 但坦率地说,我们可能 应该是。 因为如果我们继续问电脑 内存,有人喜欢的方式 GetString的,但从来没有给它回来了,肯定 那也是必然导致 据此,我们耗尽内存的问题。 而事实上,我们可以看看这些 用新的工具,其使用的问题 是有点神秘输入。 但是,让我继续前进,飞溅起来 在屏幕上一会儿就好了。 我要继续运行Valgrind的 其第一个命令与参数 行参数的名称是 ,程序HELLO-2。 不幸的是,它是 输出残暴 复杂,没有很好的理由。 所以我们看到所有的烂摊子。 大卫是说出我的名字。 所以这是程序 实际运行。 现在,我们得到如下的输出。 所以Valgrind是相似 精神GDB。 这不是一个调试器本身。 但它是一个内存检查。 这是一个程序,将运行 编程,并告诉你,如果你问了 计算机内存和从来没有把它递给 回来,因此这意味着你有 内存泄漏。 和内存泄漏往往是坏的。 你是计算机用户 大概觉得这一点,你是否有一个 Mac或PC。 您是否曾​​经使用您的电脑 而在一些没有重新启动 天,或者你刚刚得到了很多 程序运行,和那该死的东西 减慢研磨停止,或者至少 超级讨厌使用,因为 一切都只是得到了超慢。 现在,可以有任意数量的原因。 这可能是一个无限循环,一个bug 某人的代码,或者更简单地说,它 可能意味着你正在使用更多的 内存,或试图,比你 电脑实际上有。 也许有一些程序中的错误 保持内存要求。 多年的浏览器是臭名远扬 这一点,要求越来越多的内存 但从来没有将它送回。 当然,如果你只有一个有限 内存量,你不能要求 无限多次 一些该内存。 所以你在这里看到的,即使 再次Valgrind的输出是 不必要的复杂瞥一眼 首先,这是最有趣的部分。 堆 - 在出口中使用。 因此,这里是多大的内存 在使用于堆中 我的程序退出 - 显然在一个块中的6个字节。 所以,我要挥挥手 在哪一个块。 认为它就是一大块,更 技术字块。 但六个字节 - 什么是六个字节 仍在使用? 没错。 D-A-V-I-D反斜杠零,五个字母 名称加上空结束。 因此,这一计划的valgrind注意到,我 要求,很显然,由六个字节 GetString的方式,但从来没有 给他们回来。 而事实上,这可能不会是这样 很明显,如果我的程序并非三 线,但它是300线。 所以,我们其实可以给另一个命令 Valgrind的行参数 使它更详细。 要记住,这是一个有点恼人。 但如果我这样做 - 让我们来看看。 泄漏 - 被泄露 - 即使我不记得 它是什么断手。 - 泄漏检查等于已满。 是的,谢谢你。 - 泄漏检查等于已满。 回车键。 相同的程序正在运行。 再次键入大卫。 现在我看到的更详细一点。 但堆下面总结, 四是相同的 - 啊, 这是一种不错的。 现在Valgrind是实际上是在寻找 在我的代码有点困难。 和它的说,很显然, malloc的行 - 我们缩小。 行 - 我们看不出它是什么线。 但malloc的第一元凶。 有一个博客中的malloc。 没事吧? OK,没。 对吗? 我叫GetString的。 显然的getString调用malloc。 那么,什么行代码显然是 有过错 分配这个内存? 让我们假设,谁写的malloc 已经存在了足够长的时间,它是 不是他们的错。 因此,它可能是我的。 的GetString cs50.c - 所以这是一个 文件在计算机上的某个地方 - 在286行似乎是罪魁祸首。 现在,让我们假设已经CS50 围绕体面的时间量,所以 我们也有犯错误的。 因此,它可能不是的GetString 错误在于,而是在 HELLO-2.C线18。 因此,让我们一起来看看 该行18是什么。 哦。 不知怎的,这条线是不一定 越野车,本身,但它的原因是 背后的内存泄漏。 因此,超级简单,将直观地 这里的解决方案吗? 如果我们要求内存,从来没有 给它,这似乎是一个 的问题,因为随着时间的推移我的电脑 可能会耗尽内存,可能会减缓 下来,不好的事情可能会发生,好了, 简单直观的解决方案是什么? 只要给它回来。 你如何释放内存? 嗯,幸好这是相当简单 只是说免费的名字。 我们从来没有这样做过。 但你基本上可以认为 相反的malloc。 免费是相反的 分配内存。 所以现在让我重新编译。 “HELLO-2。 让我再次运行它。 HELLO-2大卫。 因此,它似乎工作 以完全相同的方式。 但是,如果我回去Valgrind的,并重新运行 我新的相同命令 编译后的程序,打字 在我的名字前 - 不错。 堆总结 - 在出口中使用 - 零字节的零块。 这是超级好看,所有 堆块被释放。 无泄漏是可能的。 因此,未来,不与习题集4 但与习题集5,取证 起,这也将成为一个 措施的正确性的 程序,不论你有 或者没有内存泄漏。 但令人欣慰的是,你不仅可以理 通过它们很直观, 可以说,是方便的小程序 但对于大型程序更难, Valgrind的,对于那些较大节目, 可以帮助您识别 特别的问题。 但是,还有另外一个问题 可能出现的。 让我在这里打开这个文件,这一点, 再次,有些简单的例子。 但是,让我们的重点放在什么 这个程序。 这就是所谓的memory.c。 在今天稍后我们将发布 今天的源代码压缩。 ,请注意,我有一个函数调用 f以不带任何参数和 返回一无所获。 在第20行,我显然声明 int和调用x的指针。 我分配的是返回 值的malloc。 只是要清楚,我多少字节 我大概从malloc 在这种情况下呢? 大概40。 你在哪儿? 好吧,如果你还记得,往往是一个int 4个字节,它是在至少 器具4的10倍,显然是40。 所以malloc的返回地址 一大块的内存和存储 在x最终解决。 所以要明确, 然后发生了什么? 好吧,让我切换回 我们这里的图片。 让我不只是画出心底 计算机的内存,让我继续前进, 绘制整个矩形, 代表我的内存。 我们会说,堆栈 是在底部。 有一个文本段 未初始化的数据。 但我只是去那些抽象 其他的东西远点,点的点。 我只是指 随着堆在上面。 然后在这幅画的底部, 代表主,我要去 给它一个片内存 在堆栈中。 F,我要去给它一个切片 内存堆栈。 现在,我咨询了我 再次源代码。 局部变量主要是什么? 显然没有,所以该片 有效空的,或者甚至还不如大 因为我已经画了。 但在F,我有一个局部变量, 被称为X。 所以我要继续前进,并得到F 一块内存,调用x。 现在malloc的10倍4, ,所以malloc的40,在哪里 内存从何而来? 我们还没有得出一个图片 像这个。 但是让我们假设,它是有效的 从这里来的,所以, 二,三,四,五。 现在我需要40。 所以我就做点,点,点建议 甚至更多的内存 回来从堆中。 现在的地址是什么? 让我们选择我们的任意 解决一如既往 - Ox123,尽管它可能会 是完全不同的东西。 这是的第一个字节的地址 内存,我要问的malloc。 因此,在短,一旦线20执行 字面意思是什么 里面存放的x? Ox123。 Ox123。 牛年是无趣的。 它只是意味着这里是一个 十六进制数。 但关键的是,我的店 在x,它是一个局部变量。 但它的数据类型,再次 是一个地址,一个int。 好吧,我要存储Ox123。 但是,如果这是一个有点太 不必要的复杂,如果我滚动 背面,我们可以抽象送人相当 合理,只是说,x是一个 该内存块的指针。 确定。 现在的问题在手 - 事实证明,21号线,是马车。 为什么呢? 对不起? 它不具有 - 说一次。 那么,它不是免费的。 所以这是第二个。 因此,有另外一个,但具体 在第21行。 没错。 这个简单的一行代码仅仅是一个 缓冲区溢出,缓冲区溢出。 只是意味着一个缓冲区的内存块。 但是,内存块的大小为 10,10的整数,这意味着,如果我们 索引使用语法糖 数组符号,广场 括号中,你有机会获得 x支架0 X支架1个, 支架点,点,点。 9 x支架是最大的一个。 所以,如果我做X支架10 实际上,我在内存中? 好吧,如果我有10个整数 - 让我们实际绘制所有 这些在这里。 所以这是第5位。 这里的其他5个int。 所以X支架0是在这里。 x支架1 在这里。 9 x支架是在这里。 x支架 10,这意味着我告诉 在第21行中,计算机把 号在哪里? 数字0在哪里? 嗯,这是0,是的。 但是,仅仅一个事实,即其0 是一种巧合。 它可能是数字 50,我们所关心的一切。 但我们正在努力把它在x支架 10,这是这 绘制问号, 是不是一件好事。 这个程序可能会非常好 崩溃的结果。 现在,让我们继续前进,看看,如果这 的确,发生了什么。 使存储器,因为该文件 被称为memory.c。 让我们继续前进,并运行 程序存储器。 所以我们很幸运,其实,它似乎。 我们很幸运。 但是,让我们来看看,如果我们现在运行Valgrind的。 乍一看,我的程序可能 似乎是完全正确的。 但让我与运行Valgrind的 - 等于内存泄漏检查。 而现在,当我运行这个 - 有意思的。 无效写大小为4 memory.c 21行。 memory.c 21号线是哪一个? 呵呵,有意思。 但等待。 尺寸4,是指什么? 我只是一个写 但它的大小为4。 为什么是4? 这是因为它是一个整数, ,再四个字节。 因此,Valgrind的,我发现了一个bug, 在我的代码一眼,没有。 ,也许你的TF会或不会。 但Valgrind的肯定发现 我们犯了一个错误,甚至 虽然我们很幸运,和电脑 决定,诶,我不会崩溃 只是因为你碰到一个字节,一个 int的内存价值,你没有 实际上是自己的。 那么,还有什么是马车。 地址 - 这是一个疯狂的寻找地址 十六进制。 这只是意味着在某处堆 零字节块大小为40后 被分配。 让我放大了这里,看看如果 这是一个多一点帮助。 有趣。 肯定失去40字节 1 1负的战绩。 同样,更多的话比在这里是非常有用的。 但基于高亮行, 我应该在哪里可能集中 关注的另一个错误? 看起来像memory.c 20行。 因此,如果我们回到20行,这就是 一个前面确定。 它不一定是马车。 但我们已经扭转其影响。 所以,我怎么至少改正 这些错误? 21号线后,我能做什么呢? 我可以做免费的X,所以 给该内存。 我怎么解决这个错误? 我绝对应该去 距离不超过0。 所以,让我尝试重新运行这个。 对不起,肯定去 距离不超过9。 使内存。 让我重新运行Valgrind的 在一个更大的窗口。 现在看。 尼斯。 所有的堆块被释放。 无泄漏是可能的。 上述这里,这里没有提到 任何无效的权利。 只是为了让贪婪,让我们 如果另一个示范 不走的打算 - 我没有得到幸运的时刻。 的事实,这是0也许是 不必要的误导。 让我们只是做50个,有点武断 电话号码,让记忆点阵斜线内存 - 仍然得到幸运。 没有崩溃。 假设我只是做一些真正 愚蠢的,我做100个。 让我重拍内存, 点斜线内存 - 很幸运了。 约1000如何? int的超越,大致 在那里我应该是什么? 使存储器 - 该死的。 [笑] 确定。 我们不是好惹的周围了。 重新运行内存。 我们去那里。 好的。 因此很明显,你100,000整数索引 超越你应该已经在 内存,不好的事情发生。 因此,这显然是不 一种坚硬,快速的规则。 我是那种使用试验 和错误到那里。 但是,这是因为,长话短说, 您的计算机的内存也划分 这些事称为段。 有时,电脑实际上 已经给你多一点的内存 比你问。 但为了提高效率,它只是更容易 获得更多的内存,但只能告诉你 你得到它的一部分。 如果你幸运,有时, 因此,您可能能够触摸 存储器中并不属于你。 你有没有保证,什么样的价值 你放在那里将呆在那里,因为 计算机仍然认为它不 你的,但它不一定要去 打另一个段中的内存 计算机和诱导这样一个错误 这一个在这里。 好的。 然后在内存中的任何问题吗? 好的。 让我们来看看这里,然后, 我们一直在服用的东西 授予相当长的一段时间, 在这个文件中称为cs50.h.的 因此,这是一个文件。 这些都只是一大堆 往上顶的意见。 你可能已经看过这个,如果 你周围戳在设备上。 但事实证明,所有的时间, 当我们使用字符串作为 同义词,手段,我们宣布 这代名词 关键字typedef的类型定义。 我们本质上说, 串一个字符星级的代名词。 的装置,通过该堆栈 这些培训车轮被称为 的字符串。 现在,这里只是一个原型 getchar的。 我们可能已经看到它之前,但是这 的确它做什么。用getchar 不带任何参数,返回一个字符。 getdouble不带任何参数, 返回一个double。 getfloat不带任何参数,返回 float,并且依此类推。 调用getInt是在这里。 getlonglong 是在这里。 和GetString是在这里。 就是这样。 这紫色的线是另一个预处理 指令,因为 包括hashtag在它的开始。 好的。 所以,现在让我进入cs50.c. 我们不会说话太长。 但给你一个什么样的一瞥 这一切一直 时间,让我去 - 让我们做getchar的。 所以getchar是主要意见。 但它看起来是这样的。 因此,这是实际的功能 我们一直用getchar 理所当然的存在。 即使我们不使用这一个 经常,如果有的话,它至少 比较简单。 因此,它是值得考虑 快看这里。 所以用getchar有一个无限循环, 显然是故意让。 然后,它调用 - 这是怎样的一个 漂亮的代码重用,我们自己写。 它调用的getString。 因为它 意味着一个char? 嗯,你不如尝试获得 从用户和整行文本 然后就看一眼 这些字符。 在60号线,这里有一个小 位神智检查。 如果GetString的返回了空, 让我们无法继续。 出了错。 现在,这是有点恼人,但 常规C.字符最大可能 代表什么 基于它的名字吗? 这是一个常数。 这就像数值 最大的字符,你可以代表 一咬,这大概是多少 255,这是最大的号码 代表8位, 从零开始。 所以,我已经使用这个,在这个函数时, 写这段代码,仅仅是因为 如果出现错误,但在用getchar 在生活中,它的目的是返回一个 字符,你需要以某种方式能 信号向用户表明 出事了。 我们不能返回null。 null是一个指针。 再次,用getchar 返回一个字符。 所以惯例,如果出现 错了,是你,程序员,或者 这种情况下,我的图书馆,我不得不 一个公正的任意决定,如果 不顺心的事,我要 返回数字255,这是真正的 意味着我们不能,用户可以不输入 表示的字符 255号,因为我们有一个偷 作为一个所谓的哨兵值 表示出现了问题。 现在事实证明,字符255 是不是,你可以输入 你的键盘,所以它是没有什么大不了的。 用户不会注意到, 我抢了这个人物。 但是,如果你看到在手册页上 计算机系统中的一些参考 帽不变,这样说, 案件中的错误这个恒定的威力 被退回,这是所有做一些人类 几年前,擅自决定 返回这个特殊的价值和 一个恒定的情况下 出现错误。 现在发生的神奇在这里。 首先,我声明在67行 两个字符,C1和C2。 然后在第68行,实际上是有 一行代码,让人想起 我们的朋友的printf,因为它 确实有百分之CS在引号中。 但是请注意,这里发生了什么。 sscanf的表示字符串扫描 - 扫描格式化 字符串,因此sscanf的。 这是什么意思? 这意味着你传递给sscanf的一个字符串。 和线无论是 用户键入 您传递给sscanf的一个格式字符串,如 这告诉scanf函数是什么 你希望用户输入。 然后,您可以通过两个地址 的内存块,在这种情况下, 因为我有两个占位符。 所以我要去给它的地址 C1和C2的地址。 记得你给一个函数 一些变量的地址,有什么 意味着什么呢? 由于该功能可以做什么 给它的地址的情况 可变的,而不是 变量本身? 它可以改变它,对不对? 如果你有某人映射到物理 地址,他们可以去那里做 无论他们想在该地址。 同样的想法在这里。 如果我们传递给sscanf的,两个地址 大块的内存,即使是这些微小的 小的块存储器,C1和C2,但是 我们告诉它的地址, sscanf的可以改变它。 所以sscanf的生活的目的,如果我们读 手册页是读什么 键入的用户,希望用户 键入一个字符,也许 另外一个角色,无论用户 键入的第一个字符进入 在这里,第二个字符到这里。 现在,顺便说一句,这,你会 只知道这个文档, 事实上,我在那里放一个空白空间 只是意味着我不关心,如果 用户点击空格键几 次之前,他或她需要 性格,我要忽略 任何空白。 所以,我知道,从 文档。 事实上,还有第二个%C 其次是白色空间实际上是 经过深思熟虑的。 我想如果用户能够检测 搞砸了或不配合。 所以,我希望用户仅键入 在一个字符,因此我希望 sscanf的是只打算返回 值1,因为再次,如果我读 文档,sscanf的目的 生活是返回的数目 充满变量 用户输入。 我通过两个变量 地址,C1和C2。 我希望,虽然,只有一个 他们被杀害,因为如果sscanf的 返回2,什么是推测 逻辑的含义? 用户不只是给我一个 性格就像我告诉他或她。 他们可能输入 至少有两个字符。 所以,如果我不是没有第二 %C,我只是有一个, 坦率地说会更直观 的做法,我觉得乍一看, 你不会是能够检测 如果用户已经给你更多 输入比你居然想。 所以这是一个隐含的形式 错误检查。 但是请注意,我在这里做什么。 我敢肯定,一旦用户给了我一个 性格,我释放就行了,做 GetString的相反,而这又 使用malloc,然后我返回 C1,我希望的字符 用户提供的,只提供了。 所以简单,但瞥见 getchar的任何问题? 我们会回来的一些其他。 好吧,让我继续前进,这样做 - 现在假设,只是为了激励我们 一个星期的讨论,加上时间,这 是一个名为structs.h。 再次强调,这仅仅是一个滋味 是摆在面前的东西。 但是请注意,很多 这是注释。 所以,我要强调只有 现在有趣的部分。 typedef的 - 再次,相同的关键字。 我们使用的typedef声明串 作为一种特殊的数据类型。 您可以使用typedef创建新品牌 数据类型时不存在 C的发明。 例如,INT与C字符 C.双与C但 有没有一个学生的概念。 然而,这将是非常有用的 能够写一个程序,存储 在一个变量中,一个学生的身份证号码, 他们的名字,他们的房子。 换句话说,三块 数据,就像一个int和一个 字符串和另一个字符串。 用typedef,什么是非常强大的 有关这个关键字sturct的 结构,你的程序员在2013年, 实际上可以定义你自己的 数据类型并不存在多年 前,但适合你的目的。 所以在这里,在13至19线, 我们宣布一个新的数据类型,如 int,但是调用它的学生。 这个变量里面去 有三样东西 - 一个int,一个字符串, 和一个字符串。 所以,你能想到什么是真正 这里发生的事情,即使这是一个 位的简化今天, 学生基本上 这个样子。 它的将是一大块 存储器与一个ID,一个名字 场,和房子的领域。 我们就可以使用这些块 记忆和访问它们,就像如下。 如果我去成struct0.c,这里是一个 比较长,但后 柄的代码 使用这种新的伎俩。 因此,首先让我提请您注意 有趣的部分往上顶。 夏普定义学生3,宣告了一个 常数,称为学生和受让人 任意3号,只是 所以我有三个学生使用 现在这个程序。 这里主要的。 通知,我怎么申报 一个阵列学生? 好吧,我只是使用相同的语法。 “学生”这个词显然是新的。 但是,学生类,支架的学生。 不幸的是,有很多 这里的重用。 这仅仅是一个数字。 因此,这是喜欢说三。 类正是我想要的 调用该变量。 我可以打电话给学生。 但类,这是不是一类的 面向对象的Java的一种方式。 这只是一个班的学生。 和数据类型中的每一个元素 该数组中是学生。 因此,这是一个有点不同 说什么 这样,它只是 - 我说给我三个学生 并调用该数组类。 好的。 现在,这里是一个四循环。 这家伙的熟悉 - 迭代 从零开始向上增加为三个。 而这里的新语法。 程序会提示我, 人类,给它一个学生 ID,这是一个int。 而这里的语法,您可以 在ID字段中存储的东西 位置类支架。所以 这个语法是不是新的。 这只是意味着给我的第八 学生在课堂上。 但这个符号是新的。 到现在为止,我们已经不能用点, 至少在这样的代码。 这意味着结构被称为 一个学生,把东西放在那里。 同样,在这下一行,31日去 来吧,把任何用户类型 这里的名字,为他们做什么 房子,同样的事情,继续前进, 把它的房子。 那么,这是什么节目 最终怎么办? 你可以看到有一点点传情。 让我继续前进,做结构0 斜线结构,学生的ID 1 0点, 大卫·马瑟说,学生证2。 罗布·柯克兰,学生证3。 劳伦Leverit - 而唯一做这个程序, 这只是完全是任意的, 我想,做一些与此数据, 现在,我已经教我们如何 使用结构,是我刚 这个额外的循环。 我遍历数组的学生。 我用了我们,也许是现在熟悉的朋友, 字符串比较,stircomp 检查第八届学生的家 等于奥美? 如果是这样,只是打印的东西 随意想,是的,它是。 但同样,只要给我机会 使用和重用, 重用这个新的点符号。 那么,谁在乎呢,对不对? 即将与学生程序是 有些武断,但事实证明, 我们可以做的有用的东西 这一点,例如,如下所示。 这是一个更复杂的结构 C.它得到了一打或更多的领域, 有些若有所思地命名。 但是,如果你曾经听说过的一个图形 称为位图文件格式,BMP, 原来,位图文件格式 相当多,这看起来像。 这是一个愚蠢的小笑脸。 这是一个小的形象,我已经放大 相当大的,所以,我可以看到每个 的单个点或像素。 现在,事实证明,我们可以代表一个 黑点,说,数字0。 和一个白点的数量1。 所以,换句话说,如果你想画一个 笑脸,并保存在该图像 的计算机,它足以存储“0”和 那些看起来像这样的,在那里, 再次,那些都是白色的 零是黑色的。 并在一起,如果你有效 一个网格的1和0,你有一个 的像素网格,如果你躺在 出来,你有一个可爱的 小笑脸。 现在,位图文件格式,BMP, 有效的引擎盖下, 但随着更多的像素SOT 实际上可以代表颜色。 但是,当你有更复杂的 如B​​MP,JPEG和GIF文件格式 你可能熟悉,那些 磁盘上的文件通常不会只 具有零和一的像素,但 他们有一些元数据,以及 - 荟萃在这个意义上是不是真的 的数据,但它是非常有用的。 因此,这些领域的暗示, 我们会看到更详细的P-集合 5,前的零点和那些 表示图像中的像素, 有一堆的元数据,如 的图像的大小和 的图像的宽度。 注意到我采摘了一些 任意的东西在这里 - 宽度和高度。 比特数和其他一些东西。 因此,有一些在一个文件中的元数据。 但是,通过了解文件规定 在这种方式,实际上,你可以 然后处理图像,图像恢复 从盘面看,调整图像。 但是,你可不一定 增强他们。 我需要的照片。 于是我又回到这里到RJ,你看到了谁 前一段时间在屏幕上。 如果我打开了主题演讲,这是 会发生什么,如果你尝试放大 加强RJ。 他没有得到任何好转真的。 现在的主题是一种模糊它 点点,只是粉饰 事实上,RJ没有得到特别 增强,当你放大。 而且如果这样做, 看到广场? 是的,你绝对可以看到 在投影机上的正方形。 这是什么时候,你得到提升。 但在如何理解我们的RJ或 笑脸的实施将让我们 其实写代码操纵 这些东西。 我想我会结束这说明, 55秒的提升的, 我不敢说,很容易误导。 [视频回放] - 他在说谎。 关于什么,我不知道。 所以我们知道什么? 这在9:15雷Santoya 在ATM。 那么问题是什么 他在9:16做? 拍摄9毫米 的东西。 也许他看到了狙击手。 或与他一起工作。 - 等待。 回到之一。 你看到了什么? 把他的脸,全屏。 他的眼镜。 有一种体现。 -这是Neuvitas的棒球队。 这是他们的标志。 他说谁 穿着那件夹克。 [END视频播放] DAVID J.马兰:这将 习题集5。 我们将看到你下周。 男扬声器:在未来CS50。 [蟋蟀的鸣叫] [音乐播放]