Placeholder Image

字幕列表 影片播放

  • 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.

    執行它的操作。