[音樂播放] 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。 [蟋蟀的鳴叫] [音樂播放]