>> [音乐播放]
>> 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。
牛年是无趣的。
它只是意味着这里是一个 十六进制数。
但关键的是，我的店 在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。
>> [蟋蟀的鸣叫]
>> [音乐播放]