字幕列表 影片播放 列印所有字幕 列印翻譯字幕 列印英文字幕 DAN ARMENDARIZ: Hi. DAN Armendariz環:你好。 I'm Dan Armendariz . 我是丹Armendariz環。 Today we're going to be looking at debugging. 今天我們將要 看著調試。 Not only are we going to talk about some techniques, 我們不僅要 談一些技巧, but also we're going to look at some of the features contained 而且我們要看看 一些特性包含 within the CS50 IDE that allow you to easily debug a program. 在CS50 IDE允許範圍內 您可以輕鬆地調試程序。 >> Just one example of something that can go wrong, >> 只是一個例子, 東西可以去錯了, and it's actually something that we've already seen before. 它實際上是什麼 我們已經看到了。 In this case, this is a C program that accepts an integer from the user, 在這種情況下,這是一個C程序 接受來自用戶的整數, divides it by 2, and provides the output back to the user. 它除以2,並提供了 輸出給用戶。 Now, from what we've seen earlier in lectures, 現在,從我們已經 在前面講課看到, we know that this will actually cause specific types of division problems 我們知道,這實際上會導致 特定類型的劃分問題 when we have odd numbers. 當我們有奇數。 Specifically, it will just throw away anything after the decimal point. 具體而言,它只是扔掉 小數點後的任何東西。 >> Now, we know that this happens to be the case. >> 現在,我們知道,這 恰好是這種情況。 And if we run it we can confirm our suspicions first by compiling 如果我們運行它,我們可以確認 我們的懷疑首先由編譯 and then by running and entering an odd number. 然後通過運行和 輸入奇數。 This is nothing new, but this is actually 這是什麼新鮮事, 但其實這是 an example of a bug that can exist within a larger program that 一個錯誤的例子,可以 在一個較大的程序存在 becomes harder to track down. 變得更難追查。 Even though we know what the issue is, the true crux of the matter 儘管我們知道是什麼問題 是,事情的真正癥結所在 might be trying to identify specifically where the error occurs, 可能會試圖確定 具體在哪裡出現錯誤, identifying what that problem is, and then fixing it. 確定是什麼問題 是,然後將其固定。 So I provide this as an example of what might be something 因此,我提供這個作為一個例子 的可能是什麼東西 that we already know but can be buried within other elements of the code. 我們已經知道,但可以埋 內的代碼的其他元素。 >> So opening this other source code file as an example, >> 所以打開這個其他來源 代碼文件作為例子, this division problem is now part of a larger program. 這種劃分問題是現在 一個較大的程序的一部分。 Still might be a little bit contrived and we 不過可能有點 有點做作我們 might be able to easily identify it, especially 可能能夠容易地 識別它,特別是 since we were just discussing this, but we 因為我們只是 討論這個,但我們 can figure out that this problem can exist on a larger scale. 可以計算出,這個問題 可在更大的範圍存在。 If I compile this and now run it, enter an odd number, 如果我編譯這個和現在 運行它,輸入一個奇數, we can see that we don't get precisely the output that we may have expected. 我們可以看到,我們沒有得到準確 我們可能預期的輸出。 In this particular case, we might say that we 在這種特殊情況下, 我們可以說,我們 want to count all the numbers from 1 up to some specific number. 要計算所有的數字 從1到一些具體數目。 And we can see that we have a variety of issues 我們可以看到,我們 有各種各樣的問題 here if we're putting simply 0 and 1 when we provide an input of 5. 在這裡,如果我們把簡單的0和 1時,我們提供的5輸入。 >> So we already know that there's a problem here. >> 因此,我們已經知道, 有一個問題在這裡。 But we may not know precisely where this issue actually exists. 但是大家可能不知道準確 其中,這個問題確實存在。 Now, one of the ways that we can try to fix this 現在,所述方法之一是 我們可以嘗試解決這個問題 is something that we've already been introduced to, 是,我們的東西 已經被引入, we can just use it on a larger scale. 我們可以只使用它在更大的規模。 On line 14 we have this printf function which 在第14行,我們有這個 printf函數這 allows us to print out the state of various pieces of information. 使我們能夠打印出狀態 的各種信息。 And this is something that you should leverage within your program 這是東西,你 應在程序中利用 to try to figure out exactly what's happening in various lines of code. 要盡量弄清楚到底是什麼 發生在各行代碼。 >> So even if this is not the final output that we actually >> 因此,即使這不是 我們實際上最終的輸出 want to produce out of this program, we still 要生產出 這個計劃,我們仍然 might have some debug statements where we 可能有一些調試 聲明我們 can try to figure out precisely what is happening inside of our code. 可以揣摩正是 正在發生的事情對我們的代碼中。 So in this case I will printf with a debug tag. 因此,在這種情況下,我會 printf輸出調試標籤。 In this case this is just a debug string that I'm 在這種情況下,這僅僅是 我是一個調試字符串 outputting so that it becomes very clear in the output of my code 輸出,使之成為非常 清晰的在我的代碼的輸出 what it is that I want to show. 它是什麼,我想展示。 And output here, the number that we have computed. 而在此輸出,數 我們已計算。 >> In this case, I might want to know precisely what is happening >> 在這種情況下,我可能要 確切地知道發生了什麼 before and after some specific computation 之前和之後的一些 具體的計算 so I might use a printf before and after that line of code. 所以我可能之前用的printf 與該行代碼後。 In this case I could even make it a little bit more clear 在這種情況下,我甚至可以使 它一點點清晰 by saying debug before and debug after so 通過之前說的調試 並經過調試等等 that I don't confuse myself with multiple lines that look identical. 我不混淆自己 多行看起來完全相同。 Now, if we recompile this and run it, enter a number like 5 again, 現在,如果我們重新編譯這個和運行 它,再輸入一個數字像5, we can see that we have now output before and after 我們可以看到,我們有 現在,前後輸出 and find that we have not done a clear division or a clear having 並發現我們沒有做過 分工明確,或明確有 of the number that we actually want to do. 數,我們 實際上想做的事情。 >> Now, in this case, this is not really a clear output. >> 現在,在這種情況下,這是 不是一個真正的清晰輸出。 It's not really a clear outcome that we want out of this particular program. 這不是一個真正的明確的結果是 我們想從這個特定的程序。 And this is, again, a little bit contrived. 這是,再等 有點做作。 But perhaps one of the things that we could 但也許之一 的事情,我們可以 do if the specification said that we want to divide this by 2 如果做規範說 我們要除以2本 and add 1-- so in other words, we want to round up-- 並添加1--因此,在其他 也就是說,我們要舍up-- then we might know that we could do that particular thing in this case. 那麼我們可能會知道,我們可以做 在這種情況下,該特定的東西。 >> Now, here we know that we will be able to add 1 to our halved number. >> 現在,在這裡,我們知道,我們將 能加1到我們的一半數量。 Let's recompile this and confirm that this 讓我們重新編譯這個 並確認此 is behaving the way that we want to. 行為是我們想要的方式。 We can see that now before having we have the number 5, 我們現在才看到, 有,我們有5號, after having we have the number 3. 有以後,我們有數字3。 Which, according to our specification, is what we wanted to do. 其中,根據我們的說明書中, 就是我們想做的事。 But if we look at the output here we can see 但是,如果我們看一下 輸出這裡我們可以看到 that we might have another bug altogether, which is 我們可能有另 完全錯誤,這是 that we are starting our count from 0. 我們是從0開始計數了。 Now again, this is something that we have seen in the past 現在再次,這是一件 我們已經看到在過去 and we can fix quite readily. 我們可以很容易解決。 But in this case we also had the benefit of using the printf statement directly 但在這種情況下,我們也有益處 直接使用printf語句的 inside of the for loop to know precisely where that error was occurring. 內部的for循環準確地知道 如該錯誤發生。 >> So printf statements are very useful in helping >> 所以printf的聲明 在幫助非常有用 you determine where precisely in your source code 你確定 正是在你的源代碼 a specific error is occurring. 一個特定的錯誤發生。 And it's also important to realize that as we're writing code, 而且這也是很重要的實現 隨著我們在寫代碼, we might have assumptions about the state of a program 大家可能都假設 關於一個程序的狀態 or we might have assumptions about what part of the program 或者我們可能有假設 關於什麼是計劃的一部分 is actually correct or incorrect. 實際上是正確或不正確的。 When later on as we build on that program 當後來因為我們 建立在該程序 and make it part of a complex and larger program, 並使其一部分 複雜的大型項目, that we realize that some aspect of that is actually buggy. 我們認識到,某些方面 那其實是馬車。 >> Using printf can really help narrow down and identify >> 用printf可以真正幫助 縮小並確定 the regions of a program that may not be behaving exactly the way that we 程序的區域可能不 要準確地行為的方式,我們 expect based on our assumptions. 基於我們的假設預期。 But there's other tools available as well 但是,還有其他 可用的工具,以及 that allow us to try to figure out where an error is occurring. 這使我們能夠揣摩 出在哪裡發生異常。 And also, specifically, what things are happening inside of the program. 而且,具體是什麼東西 正在發生的程序裡面。 So using printf is very useful when we want 因此,用printf非常 有用當我們要 to identify specific areas of a program that have some bug. 以確定的特定區域 一個程序,有一定的缺陷。 But also becomes tedious after a while. 但也成為了一段時間後乏味。 In this case, this is a relatively simple program 在這種情況下,這是一個 比較簡單的程序 with just one or two variables and it becomes very easy for us 只有一個或兩個變量 它變得很容易讓我們 to print out the value of those variables 打印出來的值 這些變量 in the context of the larger program. 在較大的程序的情況下。 >> But we might have a different program that has many variables >> 但是,我們可能有不同的 程序,有很多變數 and it may not be quite so easy to use printf 並且它可能不是很 這麼好用的printf to try to evaluate what is happening to each one of those variables 嘗試評估正在發生什麼 對這些變量中的每一個 as the program is executing. 作為上述程序的執行。 There's a program that exists called a debugger program. 有一個程序存在 所謂調試程序。 In this case, the one that we will use is the gnu debugger, or GDB, 在這種情況下,一個我們將 使用的是GNU調試器或GDB, that allows us to inspect the internal workings of a program in a much more 這使我們能夠檢查內部 一個程序的在一個更運作 detailed way. 詳細方法。 We can actually execute GDB from the command line 事實上,我們可以執行 GDB的命令行 here by simply typing GDB and the command that we want to debug. 在這裡,只需鍵入GDB和 我們要調試命令。 In this case, count. 在這種情況下,指望。 >> Now this case we can see that it brings us to a prompt that says GDB >> 現在,這種情況下,我們可以看到,它 給我們帶來了一個提示GDB,說 and we can actually execute commands to GDB to actually begin execution 我們可以實際執行命令 入庫實際開始執行 of the program, stop it at certain points, evaluate the variables, 該計劃,停止在特定 點,評估的變量, and inspect the variables that exist in the program state 並檢查變量 存在於程序狀態 at that particular moment, and so on and so forth. 在該特定時刻, 等,等等。 It provides a lot of power to us. 它提供了大量的電力給我們。 >> But it just so happens that the CS50 IDE also >> 但它只是恰巧 該CS50 IDE還 provides a GUI, or a user interface, for GDB 提供了一個GUI,或一 用戶界面,GDB that allows us to do this without needing the command line 這使我們能夠做到這一點 無需命令行 interface whatsoever. 接口任何責任。 Or at all, even. 或者可言,甚至。 The way that I can access that is by using the Debug button 我可以訪問的方法 是使用Debug按鈕 at the very top above the CS50 IDE. 在最高層以上的CS50 IDE。 Now, in the past, what we have seen is that we use the command 現在,在過去,我們所擁有的 可見的是,我們使用命令 line to compile and then run a program. 行編譯,然後運行程序。 The Debug button does both of those steps, 調試按鈕的功能 二者的那些步驟, but it also will bring up the Debugger tab on the far right 但它也帶來了 最右邊調試器選項卡 that allows us to inspect a variety properties of the program 這使我們能夠檢查一 該方案的各種性能 as it is executing. 因為它正在執行。 >> If I click Debug, in this case, it will bring up >> 如果我點擊調試,在此 情況下,它會彈出 a new tab in the console window at the very bottom. 在控制台中的新選項卡 窗口在最底層。 And you can see that this tab has some information at the very top 你可以看到這個選項卡 一些信息在最高層 and we can largely ignore this. 我們可以在很大程度上忽略了這一點。 But one of the things that we want to notice 不過的事情之一 我們要注意 is that it outputs the same thing that we 是,它輸出 同樣的事情,我們 would get if we tried to run make on the C program in the terminal window. 會得到,如果我們試圖運行make在 C程序的終端窗口。 Here we can see it's running Clang and it has a variety of flags 在這裡,我們可以看到它的運行鐺 它有各種標誌 and it is compiling our count.c file which was the selected tab at the time 並且它編譯我們count.c文件 這在當時所選標籤 that I hit Debug. 我打調試。 >> So this is very useful because now, using this Debug button, >> 因此,這是因為非常有用的 現在,使用這種調試按鈕, we can see simultaneously compile and then execute the program 我們可以同時看到編譯 然後執行該程序 that we actually want to run. 我們其實是想運行。 One of the flags that is important in this case we've actually 一的標誌是重要 在這種情況下,我們實際上已經 been using for the longest time but also just did some hand waving at, 在使用時間最長的,但 也只是做了一些手揮舞著, which is this one right here. 這是這一個就在這裡。 In clang it says -ggdb3. 在鏗鏘它說-ggdb3。 In this case, what we are telling Clang, our compiler, 在這種情況下,我們都 告訴鐺,我們的編譯器, is that we want to compile our program but also provide 就是我們要編譯 我們的計劃,但也提供了 what are called symbol information so that the compiler actually 所謂的符號信息 這樣編譯器實際上 has access to a lot of the underlying information contained 先後獲得了很多 包含的潛在信息 within the program. 在該程序。 Most specifically, the number of functions that I have, 最具體地,數 對我有作用, the names of those functions, the variables, the types 這些函數的名稱, 變量,其種類 that those variables are, and a variety of other things that help the debugger 這些變量是,和各種 其他的事情,幫助調試器 perform its operation. 執行它的操作。 Now, there's something else that's important to mention 現在,還有別的 這是重要的提 when we're discussing running a program in this way. 當我們討論運行 一個程序以這種方式。 Notice that it has actually brought up a new tab in our console 請注意,它實際上已經 提出了一個新的標籤在我們的控制台 along the bottom. 沿底部。 We no longer have to interact directly with the terminal window, 我們不再需要互動 直接與終端窗口, but this new tab is actually terminal window, 但這個新的選項卡 實際上終端窗口, it just is specific to the running program that we have created. 它只是特定於運行 我們已經創建的程序。 >> Notice that at the bottom, in combination >> 請注意,在 底部,在組合 with some output by Clang, the compiler, and GDB, which we can largely ignore, 與由鐺一些輸出,編譯器, 和GDB,我們可以在很大程度上忽略了, it actually shows the output of our program at the very bottom. 它實際上顯示的輸出 我們的節目在最底層。 Now, it's important to realize that this one window actually 現在,它要實現的重要 這一個窗口實際上 will show you the output from your program 會告訴你 從你的程序輸出 but also can accept input for that program as well. 但也可以接受輸入 該程序也是如此。 So notice that it says, please enter a number, which 所以請注意,它說, 請輸入一個數字,它 is the same output that we had had in the terminal window before 是,我們有相同的輸出 曾在之前的終端窗口 but is now shown in this new tab. 但如今在這個新的選項卡中顯示。 I can input a number and it will actually 我輸入號碼 它實際上 function as we expect showing us our debug output, the output that 功能,因為我們預計向我們展示 我們的調試輸出,輸出該 might be buggy-- as we've seen before-- and at the very bottom 可能是buggy--正如我們所看到的 before--並在最底層 it actually has some additional output from GDB just saying 它實際上有一些額外的 從GDB輸出只是說 that this program has completed. 這一方案已經完成。 >> Now, as you saw in this particular run through, it wasn't particularly useful. >> 現在,當你在這個特殊的運行鋸 通過,這不是特別有用。 Because even though we had the debugger menu come up, 因為儘管我們有 調試器菜單上來, this was still a running program. 這仍然是一個正在運行的程序。 At no point did actually pause execution for us 在任何時候,實際上做 暫停執行對我們 to be able to inspect all of the variables contained within. 要能夠檢查所有的 內包含的變量。 There's something else that we have to do in order 還有別的東西 我們必須做的,為了 to get GDB to recognize that we want to pause execution of the program 讓GDB認識到,我們要 暫停程序的執行 and not just allow it to proceed normally as we would in any other case. 而不是只允許它繼續 通常,我們會在任何其他情況下。 >> In order to pause execution at some specific line, >> 為了暫停執行 在一些具體的線路, we need to create what's called a breakpoint. 我們需要創建什麼 所謂的斷點。 And a breakpoint is very easily created in the CS50 IDE by taking your mouse 而斷點是很容易創建 在CS50 IDE通過利用鼠標 and clicking directly to the left of some specific line number. 並直接點擊向左 的一些具體的行號。 Once I do that, a red dot appears which indicates that that line is now 一旦我做到這一點,一個紅點出現 這表明該行是現在 a breakpoint, and the next time that I run GDB, 斷點,以及 下一次我運行GDB, it will stop execution at that breakpoint 它會停止執行 在那個斷點 when it reaches that line of code. 當它到達該行代碼。 >> Now, this is an important thing to realize. >> 現在,這是一個重要的 事情來實現。 That it's not necessarily the case that every line of code 這並不一定是 情況下每行代碼 is actually accessible. 實際上是訪問。 If I were to create a function up here, for example, 如果我要創建一個 這裡的功能上,例如, void f, and just do a print line here, hello world, 無效樓,只是做一個打印 此行,你好世界, if I never call this function, it will be the case that if I set a breakpoint 如果我從來沒有調用這個函數,它會 是,如果我設置一個斷點的情況下, here the function will never be called and therefore 這裡的功能永遠 被調用,因此, this particular breakpoint will never actually pause 這個特殊的斷點 將實際上從未暫停 execution of the program. 程序的執行。 >> So let's say that I correctly create a breakpoint on some line of code >> 所以我們可以說,我正確地創建 在編寫一些代碼行斷點 that will actually be executed. 實際上將被執行。 Now, in this case, this is the first line in the main function 現在,在這種情況下,這是 在主函數第一行 so it will certainly be the case that as soon as I begin execution 所以這肯定會是這樣 ,一旦我開始執行 the very first line will be reached, GDB will pause execution, 的第一行會 達,廣發行將暫停執行, and then I will be able to interact with the debugger. 然後我就可以 與調試器進行交互。 You can set multiple lines as breakpoints if you would like. 您可以設置多條線路為 斷點,如果你想。 We can also create a line up here in this segment of code 我們也可以創建一個排隊 在這裡這段代碼中 that will never be reached. 永遠不會到達。 And we can also set one further below. 而且我們還可以設置一個另外的下面。 The reason that we would want to do this we'll 究其原因,我們將 要做到這一點,我們將 go into a little bit more detail in just a moment. 進入多一點點 詳細一會兒就好了。 So for now, let me just disable these additional breakpoints 所以現在,我只想禁用 這些額外的斷點 so that we can look at what happens when I have 這樣我們就可以看 當我發生了什麼 one single breakpoint in my program. 在我的程序一個單一的斷點。 I have made some changes to this program so I need to save it. 我做了一些修改,這 程序,所以我需要保存它。 I will click Debug so that I can begin the compilation and then 我會點擊調試,這樣我就可以 開始編譯,然後 execution of the debugger. 執行調試器。 We will see that after moments the line that we selected as the breakpoint 我們將看到,片刻後 我們選作斷點行 is highlighted in yellow. 以黃色突出顯示。 We can also notice that in the upper right in the Debug panel 我們還可以看到,在 右上角的調試面板 that the Pause icon has turned into a little Play icon. 該暫停圖標已經變成 進入一個小播放圖標。 This means that we have paused execution in this particular case, 這意味著我們已暫停 執行在這種特殊情況下, and hitting the Play button will allow us to resume execution 擊中播放按鈕將 讓我們繼續執行 at that specific point. 在該特定的點。 >> Notice that there's a couple of other buttons available in this Debug panel >> 請注意,還有幾個其他的 在此調試面板可用按鈕 as well. 為好。 Step Over, which allows me to execute that one line of code 步過,這讓我 執行該一行代碼 and step over to that line to the next one. 並加強了該 行到下一個。 Which in this case would mean that the printf statement is executed 在這種情況下將意味著 執行printf語句 and it will then pause execution on line 13 like so. 它將然後暫停 執行第13行,像這樣。 And there's also a Step Into function which 而且還有一個步驟 進入功能, is useful if I have created other functions elsewhere in the source code 如果我創建了其他非常有用 別處函數的源代碼 and I want to step into those functions rather than 我想踏進 這些功能,而不是 execute that function as a whole. 執行該功能為一體。 But we'll look more at this Step Into function in just a moment. 但是,我們會看到更多的這一步 走進一會兒就好了功能。 Now, notice some other things that actually exist within this Debug panel. 現在,請注意一些其他的東西, 此調試面板中實際存在。 We have this panel called the Call Stack which shows us where exactly we are. 我們有這個小組被稱為調用堆棧 這說明我們在什麼地方,我們都是。 In this case, we are inside of the main function, our script is called count.c, 在這種情況下,我們的主要的內 功能,我們的腳本被稱為count.c, and we happen to be on line 13 column one. 我們碰巧是 上線13列之一。 Which is precisely what the highlighted region of the source code 這也恰恰是 的源代碼高亮區域 indicates as well. 表示為好。 >> Now notice that this also shows under the Local Variables section >> 現在請注意,這也顯示了 在局部變量節 all of the variables that exists within this function. 所有的變量是 存在這個函數中。 It's important to note that all of the variables 要注意這一點很重要 所有的變量的 will appear in this Local Variable section within a function 會出現在這個地方 在函數中的變量節 even before they are defined. 甚至在它們被定義。 We can see here that we have a variable called num that has a default 在這裡我們可以看到,我們有一個 變量調用NUM具有默認 value of 0 and it is of type int. 0值,它的類型為int。 Now before we actually initialize all of these variables, 現在擺在我們實際初始化 所有這些變量, we're not necessarily guaranteed to see a value of 0. 我們不一定 保證看到的值為0。 And depending on other executions that you've performed 和取決於其他 您已執行死刑 and the state of your memory when you actually run this program, 和你的內存時的狀態 你真正運行這個程序, you might find that you don't see values of 0 你可能會發現你 看不到的0值 and instead some other crazy numbers. 而是其他一些瘋狂的數字。 But don't worry about that. 但不要擔心。 It's not going to be relevant until you actually initialize the value. 它不會是相關的,直到 你居然初始化值。 >> Now, in this case, we can see that I have performed some outputs >> 現在,在這種情況下,我們可以看到 我已經進行了一些輸出 and I'm right now paused execution. 我現在是對的暫停執行。 But in this case, what I really want to do 但在這種情況下,什麼 我真正想做的事情 is to now step over this line of code so that I can actually 就是到現在跨過這條線 的代碼,這樣我實際上可以 query the user for that int that we want to use in our program. 查詢該INT用戶的 我們希望在我們的程序中使用。 Now, in this case, when I hit Step Over, notice 現在,在這種情況下,當 我打步過,通知 that the Pause-- rather the Resume button has changed to this Pause button 該Pause--寧簡歷 按鈕已更改為這個暫停按鈕 because this code is actually executing. 因為這段代碼實際上執行。 What is happening right now is that it is 這是怎麼回事 現在的問題是,它是 waiting for us to input some information as we can see by our output text 等待我們輸入一些信息 因為我們可以通過我們的輸出文本見 at the very bottom. 在最底層。 >> So right now this is not actually paused even though it sort of appears >> 所以,現在,這是不實際 停頓了一下,即使它看起來排序 to be because nothing is happening. 是因為什麼也沒有發生。 But it just so happens that in my specific case, on line 13, 但它只是恰巧,在 我的具體情況下,13號線, I'm waiting for user input and so GDB is not 我在等待用戶 輸入等GDB是不 able to inspect a program as it is running. 能夠檢查 程序作為它正在運行。 Now, the next time that I enter some input-- 現在,在下一次 我輸入一些input-- so I'll enter the number 5 as we've seen in the past, 所以我會輸入號碼5 我們已經看到,在過去, hit Return-- we notice that, immediately, GDB pauses 打Return--我們注意到, 隨即,GDB暫停 and again highlights the next line. 並再次強調了下一行。 >> But notice that now, as a result of our inputting a value, >> 但現在發現,作為 我們的輸入值的結果, we have updated that value inside of our local variables, which 我們裡面更新的價值 我們的局部變量,哪個 is very useful to know precisely what that number was in memory. 為準確地知道非常有用 是什麼數為在內存中。 Now, I can allow this program to continue 現在,我可以讓這個 程序繼續運行 playing until the end of its execution by hitting Resume. 玩到年底其 執行擊中恢復。 We can see that, very quickly, just does program finish executing 我們可以看到,很快, 只是做計劃執行完畢 with the same output that we had before. 與我們以前相同的輸出。 The debugger closes and now this program has stopped completely. 調試器關閉,現在這 程序已完全停止。 >> I show that only for the purposes of seeing what >> 我表明,只有在 用途看什麼 happens when we actually hit Resume. 發生在我們居然打簡歷。 But we actually are going to want to go back into this program 但是實際上我們要 要返回到該程序 so that we can try to debug precisely what is happening. 這樣我們就可以嘗試調試 正是正在發生的事情。 Now that I'm using the debugger I may not need these debug printf statements. 現在,我使用調試器我可能 並不需要這些調試printf的語句。 So I could remove them as I will do now. 所以,我可以將其刪除,因為我現在做的。 Just to go back to our simpler code that we had a moment ago. 剛回到我們的簡單 我們有一個剛才代碼。 >> Now, when I save the program and execute it, >> 現在,當我保存 編程並執行它, it will again go to that initial breakpoint that I had on line 11 它將再次進入初始 斷點,我對11號線 and I will be able to inspect my variables as I want to do. 我將能夠檢查 我的變量我想做的事情。 It just so happens that this part isn't very interesting. 它只是恰巧,這 部分是不是很有趣。 And I know with that I'm going to print out this statement-- 我知道有,我要去 打印出此statement-- please enter a number-- and then I know that I'm 請輸入number-- 然後我知道我 going to ask the user for that integer, so perhaps I 會詢問用戶 該整數,所以也許我 actually want to move my breakpoint a little bit further down. 其實是想將我的斷點 一點點進一步下跌。 You can remove breakpoints by clicking, again, directly 您可以刪除斷點 通過點擊,再次,直接 to the left of that line number. 到的該行編號的左側。 That red dot will disappear indicating that that breakpoint is now gone. 這紅點消失說明 該斷點現在已經沒有了。 >> Now, in this case, execution has been paused >> 現在,在這種情況下, 執行已暫停 and so it's not actually going to resume in that particular instance. 所以它實際上沒有打算 恢復在該特定實例。 But I can set a breakpoint a little bit later. 不過,我可以設置一個斷點 有點晚。 And when I now resume my code, it will resume 當我現在恢復 我的代碼,這將恢復 until the point of that breakpoint. 直到斷點的點。 Again, I hit Resume. 同樣,我打了簡歷。 Doesn't seem like anything is happening but that's 似乎並不像什麼 正在發生的事情,但是這 because my code is waiting for input. 因為我的代碼正在等待輸入。 I will enter a number 5, hit Enter, and now the next breakpoint will be hit. 我將進入5號,敲回車,和 現在,下一個斷點將受到重創。 >> Now in this case, this is the line of code that before we knew >> 現在,在這種情況下,這是 代碼,我們知道前行 happened to be buggy. 正好是馬車。 So let's evaluate what happens at this particular point in time. 因此,讓我們評估發生了什麼 在這一時代的特殊點。 When a line is highlighted, this line has not yet been executed. 當行被突出顯示,該 線尚未被執行。 So in this case, we can see that I have a number which-- 所以在這種情況下,我們可以看到 我有一些which-- I have an integer with-- called num that has a value 5 我有一個整數with-- 所謂NUM具有值為5 and I'm going to be performing some math on that number. 而我要表演 一些數學上的那個數字。 If I step over that, we can notice that the value for num 如果我跳過了,就可以 請注意,對於NUM值 has changed in accordance with the arithmetic that we've actually done. 按照已經改變 算術,我們實際上已經完成。 And now that we are inside of this for loop, 而現在,我們 這個循環裡面, or now that the for loop itself is highlighted, 還是現在的for循環 本身是突出, we see that we have a new variable called i that 我們可以看到,我們有一個新的 變量調用我的 is going to be used in that for loop. 將被用在該for循環。 >> Now, remember before that I mentioned that sometimes you're >> 現在,我還記得之前 提到,有時你 going to see some kind of crazy numbers until-- as default before that number 會看到一些瘋狂的數字 until--默認該號碼 or that variable is actually initialized. 或者變量 實際上初始化。 We can see that precisely here in this variable 我們可以看到,正是 這裡在該變量 called i which has not yet been initialized 叫我一直沒有 尚未初始化 at the time of highlighting, but we can see 在時間 突出,但是我們可以看到 that it has some number that we wouldn't actually expect. 它具有一些數量 我們也不會真正期望的。 That's OK. 這是確定的。 Don't worry about it because we have not actually 別擔心 因為我們有沒有真正 initialized that number until I step over this line and the value 初始化的數量,直到我 跨過這條線與價值 i has been initialized to the value 1. 我已經被初始化為值1。 >> So to see that that's actually the case, let's step over. >> 所以一看就知道這其實 的情況下,讓我們跳過。 We can now see that that line has been executed 現在我們可以看到,這 線已經被執行 and we are now highlighting this printf line. 我們現在強調 這個printf的線。 And we can now see how our values of i and 3 have changed over time. 我們現在可以看到我們是如何價值觀 i和3隨時間而變化。 This is very useful to do, in fact, is to step over lines repeatedly. 這是非常有用的事,事實上, 是重複步過線。 And you can find what actually happens inside of your for loop 你可以找到真正是什麼 碰巧你對循環內 and what happens to the variables inside of that for loop 並會發生什麼變化 變量內,對於環 as that program execution occurs one step at a time. 作為程序執行 發生一步一個腳印的時間。 >> Now, at this point I stepped over just enough >> 現在,在這一點上我 跨過剛好夠用 that I now am at the end of my program. 那我現在在我的程序結束。 If I step over that, it will actually cease execution 如果我跨過,它會 實際上停止執行 as we have seen in the past. 正如我們已經看到在過去。 Let me restart this yet again so that I can point something else out as well. 讓我重新啟動此再次使 我可以點別的東西出來為好。 In this case, it is now asking me, again, 在這種情況下,它是 現在問我,再次, for a number which I will again enter. 對於一些我將再次進入。 But this time I'm going to enter in a larger number so that the for loop 但是,這一次我要進入 數量較多,使得循環 will iterate more times. 將重複多次。 In this case I'm going to enter a value of 11. 在這種情況下,我會 輸入值11。 >> Now, again, because I'd set a breakpoint at line 15, >> 現在,再次,因為我已經設置 斷點在第15行, it's going to highlight that line. 它會高亮顯示該行。 We can see that our number 11 is correctly 我們可以看到,我們的 11號是正確的 represented in our local variables. 代表我們的局部變量。 Stepping over that we can now watch what happens to our value of i 步過,我們現在可以看 發生在我們的I值是什麼 as we proceed inside of this for loop. 當我們著手這裡面的for循環。 It gets incremented every time we reach the top of that for loop. 它被遞增每次我們 達到了頂部循環。 >> Now, one of the things that might be useful to do during execution >> 現在,這可能的事情之一 是有用的執行過程中做 of this program is really to actually change the variables midstream 這個程序是真正實際 改變變量中游 to see what happens to my program. 要看看會發生到我的計劃是什麼。 In this case I can actually double click the value. 在這種情況下,我其實可以 雙擊該值。 Notice that it becomes a text field. 請注意,它變成了文本字段。 Now I can enter a different value altogether 現在,我可以輸入 不同的價值完全 to see how my program behaves when I've changed that variable. 怎麼看我的程序的行為 當我改變了這一切變化。 >> Now in this case, the variable i now contains the value 10 >> 現在,在這種情況下,可變 我現在包含值10 but the program is still paused in execution. 但該計劃仍是 在暫停執行。 When I step over, I see that i-- the value i which I entered as 10 當我踏上了過來,我看到我 - 這是我進入10 i的值 is now greater than the value of num which immediately causes the for loop 現在比num的值越大 這立即引起了循環 to stop executing. 停止執行。 Now that's not the only reason why you would 現在,這不是唯一的 你之所以會 want to modify the variable in place. 要修改的變量的地方。 You might actually want to try to modify it so 你可能真的想 嘗試修改它, that you can continue execution of a loop 您可以繼續 執行一個循環 or so that you can modify some value before it 或者,讓你可以修改 之前,一些價值 reaches some specific set of arithmetic that you are about to perform. 達到某些特定的算術 你是要執行。 So now that we've actually changed the value of i 所以,現在我們實際上已經 改變的i的值 as the program was executing, it caused the for loop 作為該計劃正在執行, 它造成的for循環 to quit prematurely because all a sudden i happened 過早地因為退出 突然,我碰巧 to be greater than the value of num. 為大於num的值。 Meaning that that for loop no longer needed to be executed. 這意味著,對於循環中沒有 不再需要被執行。 Further, it happened to be the case that we changed the value of i 此外,它正好是 情況下,我們改變了我的價值 when the line 17 was highlighted which was the point in time 該行17強調,當 這是在時間點 that the for loop execution was actually being evaluated. 該循環執行 實際上正在評估。 If I had changed the value of i on a different line, say 19, 如果我改變的價值 我在不同的線路,比如19, we would have seen different behavior because line 19 would 我們會看到不同的 問題是因為19行會 have executed before the loop condition was reevaluated. 循環之前已經執行 條件進行重新評估。 >> Now at this point, I'm, again, at the end of this program >> 現在,在這一點上,我再次, 在這個程序結束 and I can allow this to proceed to allow my program to quit naturally. 我可以讓這種情況繼續 讓我的程序自然退出。 But there's a couple of things that are important to take away 但有幾件事情 這是很重要的帶走 from this particular discussion. 從這個特定的討論。 You need to evaluate your own assumptions 您需要評估 你自己的假設 about how the code should be behaving. 有關如何代碼應表現。 Any time you think that some piece of code you know happens to work, 任何時候你覺得有些片 你知道發生了代碼工作, that might be a red flag to go back and evaluate and be sure 這可能是一個紅旗去 回顧和評估,並確保 that your assumption of how that code is operating 你的假設 如何代碼運行 is actually true to how it is expressed in your source code. 其實真到是怎麼回事 表現在你的源代碼。 >> But even more to point was when we were using the debugger. >> 但更要的一點是,當 我們使用調試器。 You can put breakpoints at different lines of code 你可以把斷點 在不同的行代碼 which will cause the debugger to pause execution at each of those lines 這將導致調試器 暫停執行在每個那些行 so that you can evaluate the memory or even change it in place. 這樣就可以評估 內存甚至改變它在的地方。 And again, remember that you can create multiple breakpoints so that you 再次,請記住,你可以 創建多個斷點,這樣你 can also resume execution, skip over large portions of code, 也可以繼續執行,跳躍 以上代碼的大部分, and it will automatically pause at the next breakpoint. 它會自動 暫停在下一個斷點。 >> There's actually more advanced features of the debugger as well. >> 實際上有更先進 調試器的功能,以及。 But we'll have to refer you to some subsequent videos 但是,我們必須向您推薦 一些後續的視頻 in order to really tease apart how to use those particular functions. 要真正梳理出怎麼樣 使用這些特定的功能。 For now, thank you very much for watching and good luck debugging. 現在,非常感謝你的 看,祝你好運調試。
B1 中級 中文 程序 執行 代碼 輸出 情況 實際 節。和丹-阿門達里茲一起調試 (Section: Debugging with Dan Armendariz) 101 5 Amy.Lin 發佈於 2021 年 01 月 14 日 更多分享 分享 收藏 回報 影片單字