Visual C++ 6.0調(diào)試功能
這是我自己在學(xué)習(xí)時(shí)整理的,希望對(duì)大家有用.其中有幾個(gè)部分的內(nèi)容,如下:
※My Note
全部由我截圖并參考資料進(jìn)行說明,這其中有大量的內(nèi)容是調(diào)試過程中體會(huì)總結(jié)才寫的.有不當(dāng)之處請(qǐng)大家更正.
※From 《Visual C++ Debugger》
這本書寫得非常的不錯(cuò),從里面截了一些有用的圖,主要是強(qiáng)烈推薦大家閱讀這本書.
※Debug Menu From MSDN
這是我從Visual C++ 6.0 MSDN Library October 2001中查來的,在My Note中有很多是從那里參考的.強(qiáng)烈推薦大家看這份英文說明.
※From 《visual C++ 6.0開發(fā)工具與調(diào)試》
這是我從網(wǎng)絡(luò)上搜索到的,問題很經(jīng)典,強(qiáng)烈推薦大家參看學(xué)習(xí),避免不必要的錯(cuò)誤.
?
?
My Note
○常用功能:
?
?
?
?
Restart(
Ctrl+shift+F5):此debugger功能將從程序的開始(第一有效行)處全速執(zhí)行,而不是從當(dāng)前所跟蹤的位置開始調(diào)
試,這時(shí)所有變量的當(dāng)前值都將被丟棄,debugger會(huì)自動(dòng)停在程序的main()開始處.這時(shí)如果選擇Step Over(F10)就可以逐步執(zhí)行main()函數(shù)了.
Stop Debugging(
Shift+F5):此debugger功能將終止(所有)調(diào)試,并返回到常規(guī)編輯狀態(tài).
Break(
此功能常常在遇到調(diào)用函數(shù)的語句時(shí)可見.):此功能將在調(diào)試過程中的debugger當(dāng)前位置掛起程序的執(zhí)行,然后就可以在調(diào)
試狀態(tài)一修改程序的代碼,接著可以用Apply Code Changes(Alt+F10)來應(yīng)用修改的代碼到正在調(diào)試的程序當(dāng)中.如果,當(dāng)前(需要,待)可以(從DOS
等窗口)輸入值,掛起后將不能再輸入.
Apply Code Changes(
Alt+F10):此功能可以在程序正在調(diào)試程序過程中應(yīng)用(掛起)修改后的源代碼.如,選擇
Break功能并修改代
碼后,只要選擇Apply Code Changes(Alt+F10)就能將修改后的代碼應(yīng)用到正在調(diào)試的程序當(dāng)中.
Show Next Statement(
Alt+Num*):此功能將顯示程序代碼的下一條語句,如果源代碼中找不到,則在Disassembly窗口中顯示語句.
當(dāng)在Disassembly窗口中顯示時(shí),可以單擊
Disassembly 返回到源代碼窗口.
Step Into(
F11):此功能可以單步進(jìn)入到在調(diào)試過程中所跟蹤的調(diào)用函數(shù)的語句的函數(shù)內(nèi)部.如,當(dāng)前語句是"d.Display()",
選擇Step Into(F11)后,Debugger將進(jìn)入Display()函數(shù)內(nèi)部并停在Display()函數(shù)內(nèi)部的第一條語句上.(此時(shí),
就可以Step Over(F10)對(duì)Display()函數(shù)進(jìn)行單步調(diào)試了.)
Step Over(
F10):此功能可以單步對(duì)所在函數(shù)單步調(diào)試,如果調(diào)試的語句是一個(gè)調(diào)用函數(shù)的語句時(shí),
Debugger將全速執(zhí)行所調(diào)用的函數(shù),單步(一步)通過所調(diào)用的函數(shù),Debugger停該調(diào)用語句的下一條語句上.
Step Out(
Shift+F11):此功能將使Debugger切換回全速執(zhí)行到被調(diào)用函數(shù)結(jié)束,并停在該函數(shù)調(diào)用語句的下一條語句上.
當(dāng)確定所調(diào)用的函數(shù)沒有問題時(shí)可以用這個(gè)功能全速執(zhí)行被調(diào)用函數(shù).
Run to Cursor(
Ctrl+F10):此功能將全速執(zhí)行到包含插入點(diǎn)光標(biāo)所在的行,可以作為在插入點(diǎn)光標(biāo)處設(shè)置常規(guī)斷點(diǎn)的一種選擇.
注意,當(dāng)光標(biāo)處不是一個(gè)有效的執(zhí)行語句時(shí)此功能將不起作用.
Go(
F5):此功能將全速執(zhí)行程序直到遇到一個(gè)斷點(diǎn)或程序結(jié)束,或直到程序暫停等待用戶輸入.
注意,此功能最能有效的調(diào)試循環(huán),常將斷點(diǎn)設(shè)置在循環(huán)體內(nèi),重復(fù)的按F5全速執(zhí)行循環(huán)體可以測(cè)試循環(huán)過程中的產(chǎn)生的變化.
Step Into Specific Function:此功能可以可以單步通過程序中的指令,并進(jìn)入指定的函數(shù)調(diào)用,此功能對(duì)于函數(shù)的嵌套層不限.
?
?
?
?
?
?
?
?
調(diào)試常用快捷鍵
單步進(jìn)入 | F11 |
單步跳過 | F10 |
單步跳出 | SHIFT+F11 |
運(yùn)行到光標(biāo) | CTRL+F10 |
開關(guān)斷點(diǎn) | F9 |
清除斷點(diǎn) | CTRL+SHIFT+F9 |
Breakpoints(斷點(diǎn)管理) | CTRL+B 或ALT+F9 |
GO | F5 |
Compile(編譯,生成.obj文件) | CTRL+F7 |
Build(組建,先Compile生成.obj再Link生成.exe) | F7 |
?
?
From 《Visual C++ Debugger》
?
?
Debug Menu From MSDN
Start Debug Commands (Build menu)
Menu command | Action
|
Go | Executes code from the current statement until a breakpoint or the end of the program is reached, or until the application pauses for user input. (Equivalent to the Go button on the toolbar.) |
Step Into | Single-steps through instructions in the program, and enters each function call that is encountered. |
Run to Cursor | Executes the program as far as the line that contains the insertion point. This is equivalent to setting a temporary breakpoint at the insertion point location. |
Attach to Process | Attaches the debugger to a process that is running. Then you can break into the process and perform debugging operations like normal. |
When you begin debugging, the Debug menu appears, replacing the Build menu on the menu bar. You can then control program execution using the commands
listed in the following table.
Debug Menu Commands that Control Program Execution
Debug menu command | Action
|
Go | Executes code from the current statement until a breakpoint or the end of the program is reached, or until the application pauses for user input. (Equivalent to the Go button on the Standard toolbar.) When the Debug menu is not available, you can choose Go from the Start Debug submenu of the Build menu. |
Restart
| Resets execution to the first line of the program. This command reloads the program into memory, and discards the current values of all variables (breakpoints and watch expressions still apply). It automatically halts at the main(
) or WinMain(
) function. |
Stop Debugging
| Terminates the debugging session, and returns to a normal editing session. |
Break
| Halts the program at its current location. |
Step Into | Single-steps through instructions in the program, and enters each function call that is encountered.? When the Debug menu is not available, you can choose Step Into from the Start Debug submenu of the Build menu. |
Step Over | Single-steps through instructions in the program. If this command is used when you reach a function call, the function is executed without stepping through the function instructions. |
Step Out | Executes the program out of a function call, and stops on the instruction immediately following the call to the function. Using this command, you can quickly finish executing the current function after determining that a bug is not present in the function. |
Run to Cursor | Executes the program as far as the line that contains the insertion point. This command is equivalent to setting a temporary breakpoint at the insertion point location. When the Debug menu is not available, you can choose Run To Cursor from the Start Debug submenu of the Build menu. |
Step Into Specific Function | Single steps through instructions in the program, and enters the specified function call. This works for any number of nesting levels of functions. |
The following additional commands appear on the Debug menu:
Exceptions | Displays the Exceptions dialog, which you can use to specify how you want the debugger to handle your program exceptions. |
Threads | Displays the Threads dialog, which you can use to suspend, resume, or set focus to progam threads. |
Show Next Statement | Shows the next statement in your program code. If source code is not available, displays the statement within the Disassembly window. |
QuickWatch | Displays the Quick Watch window, where you can work with expressions. |
?
?
?
?
From 《visual C++ 6.0開發(fā)工具與調(diào)試》
1、????????? 如何快速地規(guī)范代碼縮進(jìn)格式
選中所需要規(guī)范的代碼,按shift+F8
2、????????? 如何在Release狀態(tài)下進(jìn)行調(diào)試
Project->Setting=>ProjectSetting對(duì)話框,選擇Release狀態(tài)。C/C++標(biāo)簽中的Category選General,Optimizations選Disable(Debug),
Debut info選Program Database。在Link標(biāo)簽中選中Generate debug info復(fù)選框。
? ?
?
注:只是一個(gè)介乎Debug合Release的中間狀態(tài),所有的ASSERT、VERIFY都不起作用,函數(shù)調(diào)用方式已經(jīng)是真正的調(diào)用,而不查表,
但是這種狀態(tài)下QuickWatch、調(diào)用隊(duì)列跟蹤功能仍然有效,和Debug版一樣。
? ?
?
3、????????? Release和Debug有什么不同。
Release版稱為發(fā)行版,Debug版稱為調(diào)試版。
Debug中可以單步執(zhí)行、跟蹤等功能,但生成的可執(zhí)行文件比較大,代碼運(yùn)行速度較慢。Release版運(yùn)行速度較快,可執(zhí)行文件較小,
但在其編譯條件小無法執(zhí)行調(diào)試功能。
Release的exe文件鏈接的是標(biāo)準(zhǔn)的MFC DLL(Use MFC in a shared or static dll),比如MFC42.DLL。這些DLL在安裝Windows的時(shí)候,
已經(jīng)配置,所以這些程序能夠在沒有安裝Visual C++ 6.0的機(jī)器上運(yùn)行。而Debug版本的exe鏈接了調(diào)試版本的MFC DLL文件,如MFC42D.DLL。
在沒有安裝Visual C++6.0的機(jī)器上不能運(yùn)行,因為缺MFC42D.DLL等,除非選擇use static dll when link。
? ?
?
4、????????? ASSERT和VERIFY有什么區(qū)別
ASSERT里面的內(nèi)容在Release版本中不編譯,VERIFY里面的內(nèi)容仍然翻譯,但不再判斷真假。所以后者更安全一點(diǎn)。
例如ASSERT(file.Open(strFileName))。
一旦到了Release版本中,這一行就忽略了,file根本就不Open()了,而且沒有任何出錯(cuò)的信息。如果用VERIFY()就不會(huì)有這個(gè)問題。
? ?
?
5、????????? Workspace和Project之間是什么樣的關(guān)系
每個(gè)Workspace可以包括幾個(gè)project,但只有一個(gè)處于Active狀態(tài),各個(gè)project之間可以有依賴關(guān)系,在project的Setting..中可以設(shè)定,
比如那個(gè)Active狀態(tài)的project可以依賴于其他的提供其函數(shù)調(diào)用的靜態(tài)庫。
? ?
?
6、????????? 如何在非MFC程序中使用ClassWizard
在工程目錄下新建一個(gè)空的.RC文件,然后加入到工程中就可以了。
? ?
?
7、????????? 如何設(shè)置斷點(diǎn)
按F9在當(dāng)前光標(biāo)處增加一個(gè)斷點(diǎn)和取消一個(gè)斷點(diǎn)。
另外,在編輯狀態(tài)下,按Ctrl+B組合鍵,彈出斷點(diǎn)設(shè)置對(duì)話框。然后單擊【Condition…】按鈕彈出設(shè)置斷點(diǎn)條件的對(duì)話框進(jìn)行設(shè)置。
? ?
?
8、????????? 在編輯狀態(tài)下發(fā)現(xiàn)成員變量或函數(shù)不能顯示提示是如何打開顯示功能
這似乎是目前這個(gè)Visual C++ 6.0版本的一個(gè)bug,可按如下步驟使其正常,如再出現(xiàn),可如法炮制:
(1)???????????? 關(guān)閉Project
(2)???????????? 刪除"工程名.ncb"文件
(3)???????????? 重新打開工程
? ?
?
9、????????? 如何將一個(gè)通過ClassWizard生成的類徹底刪除
首先在工作區(qū)的FileView中選中該類的.h和.cpp文件,按delete刪除,然后在文件管理器中將這兩個(gè)文件刪除,再運(yùn)行ClassWizard,
這時(shí)出現(xiàn)是否移走該類的提示,選擇remove就可以了。
? ?
?
10、???? 如何將再workspace中消失的類找出來
打開該類對(duì)應(yīng)的頭文件,然后將其類名隨便改一下,這個(gè)時(shí)候工作區(qū)就會(huì)出現(xiàn)新的類,再將這個(gè)類改回原來的名字就可以了。
? ?
?
11、???? 如何清除所有的斷點(diǎn)
菜單【Edit】->【Breakpoints…】,打開"Breakpoints"對(duì)話框,單擊【Remove All】按鈕即可。
快捷鍵是"Ctrl + Shift + F8"。
? ?
?
12、???? 如何再ClassWizard中選擇未列出的信息
打開"ClassWizard"對(duì)話框,然后切換到"Class Info"頁面。改變"Message filter",如選擇"Window","Message"頁面就會(huì)出現(xiàn)Window的信息。
? ?
?
13、???? 如何檢測(cè)程序中的括號(hào)是否匹配
把光標(biāo)移動(dòng)到需要檢測(cè)的括號(hào)前面,按快捷鍵"Ctrl + ]"。如果括號(hào)匹配正確,光標(biāo)就跳到匹配的括號(hào)處,否則光標(biāo)不移動(dòng),
并且機(jī)箱喇叭還會(huì)發(fā)出一聲警告。
? ?
?
14、???? 如何查看一個(gè)宏(或變量、函數(shù))的定義
把光標(biāo)移動(dòng)到要查看的一個(gè)宏上,就比如說最常見的DECLARE_MAP_MESSAGE上按一下F12(或右鍵菜單中的相關(guān)菜單),
如果沒有建立瀏覽文件,就會(huì)出現(xiàn)提示對(duì)話框,按【確定】按鈕,然后就會(huì)跳到該宏(或變量、函數(shù))定義的地方。
? ?
?
15、???? 如何添加Lib文件到當(dāng)前工程
單擊菜單【Project】->【Settings…】彈出"Project Setting"對(duì)話框,切換到"Link"標(biāo)簽頁,在"Object/library modules"處輸入Lib文件名稱,
不同的Lib之間用空格格開。
? ?
?
16、???? 如何快速刪除項(xiàng)目下的Debug文件夾中臨時(shí)文件
在工作區(qū)的FileView視圖中選中對(duì)應(yīng)的項(xiàng)目,單擊右鍵彈出菜單,選擇【Clean(selection only)】菜單即可。
? ?
?
17、???? 如何快速生成一個(gè)現(xiàn)有工程除了工程名外完全相同的新工程。
在新建工程的"New"對(duì)話框中選擇"Custom Appwizard"項(xiàng),輸入新工程的名字,單擊【OK】按鈕。出現(xiàn)"Custom AppWizard"項(xiàng),
輸入新工程的名字,單擊【OK】按鈕。出現(xiàn)"Custom AppWizard-Step 1 of 2"對(duì)話框,選擇"An existing Project"項(xiàng),單擊【Next】按鈕。
出現(xiàn)"Custom AppWizard-Step 2 of 2"對(duì)話框,選擇現(xiàn)有工程的工程文件名,最后單擊【Finish】按鈕。編譯后就生成一個(gè)與現(xiàn)有工程相同
但可以重新取名的工程AppWizard。
現(xiàn)在就可以項(xiàng)用MFC AppWizard一樣用這個(gè)定制的向?qū)?。如果不想用了,可以?span style="font-family:Gulim">Visual C++ 6.0安裝目錄下Common\MSDev98\Template目錄
中刪除該Wizard對(duì)應(yīng)的.awx和.pdb文件。
? ?
?
18、???? 如何解決Visual C++ 6.0不正確連接的問題
情景:明明之間改動(dòng)了一個(gè)文件,卻要把整個(gè)項(xiàng)目全部重新編譯鏈接一次。剛剛鏈接好,一運(yùn)行,有提示重新編譯鏈接一次。
這是因?yàn)槌霈F(xiàn)了未來文件(修改時(shí)間和創(chuàng)建時(shí)間比系統(tǒng)時(shí)間晚)的緣故。可以這樣處理:找到工程文件夾下的debug目錄,
將創(chuàng)建和修改時(shí)間都比系統(tǒng)時(shí)間的文件全部刪除,然后再從新"Rebuild All"一次。
? ?
?
19、???? 引起LNK2001的常見錯(cuò)誤都有哪些
遇到的LNK2001錯(cuò)誤主要為:unresolved external symbol "symbol"
如果鏈接程序不能在所有的庫和目標(biāo)文件內(nèi)找到所引用的函數(shù)、變量或標(biāo)簽,將產(chǎn)生此錯(cuò)誤信息。
一般來說,發(fā)生錯(cuò)誤的原因有兩個(gè):一時(shí)所引用的函數(shù)、變量不存在,拼寫不正確或者使用錯(cuò)誤;其次可能使用了不同版本的鏈接庫。
一下是可能產(chǎn)生LNK2001錯(cuò)誤的原因:
<1>由于編碼錯(cuò)誤導(dǎo)致的LNK2001錯(cuò)誤
不相匹配的程序代碼或模塊定義(.DEF)文件導(dǎo)致LNK2001。例如,如果在C++源文件了內(nèi)聲明了一變量"var1",
卻視圖在另一個(gè)文件內(nèi)以變量"var1"訪問改變量。
(2)???????????? 如果使用的內(nèi)聯(lián)函數(shù)是在.cpp文件內(nèi)定義的,而不是在頭文件內(nèi)定義將導(dǎo)致LNK2001錯(cuò)誤。
(3)???????????? 調(diào)用函數(shù)是如果所用的參數(shù)類型頭函數(shù)聲明是的類型不符將會(huì)產(chǎn)生LNK2001錯(cuò)誤。
(4)???????????? 視圖從基類的構(gòu)造函數(shù)或析構(gòu)函數(shù)中調(diào)用虛擬函數(shù)時(shí)將會(huì)導(dǎo)致LNK2001錯(cuò)誤。
(5)???????????? 要注意函數(shù)和變量的可公用性,只有全局變量、函數(shù)時(shí)可公用的。靜態(tài)函數(shù)和靜態(tài)變量具有相同的使用范圍限制。
當(dāng)試圖從文件外部方位任何沒有在該文件內(nèi)聲明的靜態(tài)變量時(shí)將導(dǎo)致編譯錯(cuò)誤或LNK2001錯(cuò)誤。
<2>由于編譯和聯(lián)機(jī)的設(shè)置而造成的LNK2001錯(cuò)誤
如果編譯時(shí)使用的時(shí)/NOD(/NODERAULTLIB)選項(xiàng),程序所需要的運(yùn)行庫和MFC時(shí)將得到又編譯器寫入目標(biāo)文件模塊,
但除非在文件中明確包含這些庫名,否則這些庫不會(huì)北鏈接進(jìn)工程文件。這種情況下使用/NOD將導(dǎo)致LNK2001錯(cuò)誤
如果沒有為wWinMainCRTStartup設(shè)定程序入口,在使用Unicode和MFC時(shí)講的到
"unresolved external on _WinMain@16"的LNK2001錯(cuò)誤信息。
使用/MD選項(xiàng)編譯時(shí),既然所有的運(yùn)行庫都被保留在動(dòng)態(tài)鏈接庫之內(nèi),源文件中對(duì)"func"的引用,
在目標(biāo)文件里即對(duì)"__imp__func"的引用。如果試圖使用靜態(tài)庫LIBC.LIB或LIBCMT.LIB進(jìn)行鏈接,將在__imp__func上發(fā)生LNK2001錯(cuò)誤。如果不使用/MD選項(xiàng)編譯,在使用MSVCxx.LIB鏈接時(shí)也會(huì)發(fā)生LNK2001錯(cuò)誤。
(4)???????????? 使用/ML選項(xiàng)編譯時(shí),如用LIBCMT.LIB鏈接回在_errno上發(fā)生LNK2001錯(cuò)誤。
(5)???????????? 當(dāng)編譯調(diào)試版的應(yīng)用程序時(shí),如果采用發(fā)行版模態(tài)庫進(jìn)行鏈接也會(huì)產(chǎn)生LNK2001錯(cuò)誤;同樣,
使用調(diào)試版模態(tài)庫鏈接發(fā)行版應(yīng)用程序時(shí)也會(huì)產(chǎn)生相同的錯(cuò)誤。
(6)???????????? 不同版本的庫和編譯器的混合使用也能產(chǎn)生問題,因?yàn)樾掳娴膸炖锟赡馨缦鹊陌姹緵]有的符號(hào)和說明。
(7)???????????? 在不同的模塊中使用內(nèi)聯(lián)和非內(nèi)聯(lián)的編譯選項(xiàng)能夠?qū)е?span style="font-family:Gulim">LNK2001錯(cuò)誤。如果創(chuàng)建C++庫時(shí)打開了
函數(shù)內(nèi)聯(lián)(/Ob1或/Ob2),但是在描述該函數(shù)的相應(yīng)頭問卷安里卻關(guān)閉了函數(shù)內(nèi)聯(lián)(沒有inline關(guān)鍵字),
只是將得到錯(cuò)誤信息。為避免該問題的發(fā)生,應(yīng)該在相應(yīng)的頭文件中用inline關(guān)鍵字標(biāo)志為內(nèi)聯(lián)函數(shù)。
(8)???????????? 不正確的/SUBSYSTEM或ENTRY設(shè)置也能導(dǎo)致LNK2001錯(cuò)誤。
? ?
?
20、???? 如何調(diào)試一個(gè)沒有源碼的exe文件調(diào)用的dll
在Visual C++ 6.0中,進(jìn)入"Project Setting"對(duì)話框然后選擇Debug標(biāo)簽頁。通常Visual Studio默認(rèn)"executable for debug session"為可執(zhí)行文件名,
但可以將他改成任何你想要的程序。甚至可以指定不同的工作目錄以及傳遞參數(shù)到你的程序。這個(gè)技術(shù)常用來調(diào)試Dlls、名字空間擴(kuò)展、
COM對(duì)象和其他從某些EXE以及從第三方的EXE中調(diào)用的plug-in程序。
? ?
?
21、???? Visual C++ 6.0工程中的項(xiàng)目文件都表示什么。
.opt:工程關(guān)于開發(fā)化境的參數(shù)文件。如工具條位置等信息。
.aps(AppStudio File)資源輔助文件,二進(jìn)制格式,一般不用去管他。
.clw:ClassWizard信息文件,實(shí)際上是INI文件格式,又興趣可以研究一下。有時(shí)候ClassWizard出了問題,手工修改CLW文件可以解決。
如果此文件不存在的話,每次用ClassWizard的時(shí)候回提示是否重建。
.dsp(DevelopStudio Project):項(xiàng)目文件,文本格式,不過不熟悉的或不要手工修改。
.dsw(DevelopStudio Workspace):是工作區(qū)文件,其他特點(diǎn)和.dsp差不多。
.plg:是編譯信息文件,編譯時(shí)的error和warning信息文件(實(shí)際上時(shí)一個(gè)html文件),一般用處不大。在單擊菜單【Tool】->【Option】
彈出的對(duì)話框里面有個(gè)選項(xiàng)可以控制這個(gè)文件的生成。
.hpj(Help Project):是生成幫助文件的工程,用microsoft Help Compiler可以處理。
.mdp(Microsoft DevStudio Project):是舊版本的項(xiàng)目文件,如果要打開此文件的話,回提示你是否轉(zhuǎn)換成新的.dsp格式。
.bsc:是用于瀏覽項(xiàng)目信息的,如果用Source Brower的話舊必須又這個(gè)文件。如果不用這個(gè)功能的話,可以在Project Options里面去掉
Generate Browse Info File,這樣可以加快編譯速度。
.map是執(zhí)行文件的影像信息記錄文件,除非對(duì)系統(tǒng)底層,這個(gè)文件一般用不著。
.pch(Pre-Compiled File):是與編譯文件,可以加快編譯速度,但是文件非常大。
.pdb(Program Database),記錄了程序有關(guān)的一些數(shù)據(jù)和調(diào)試信息,在調(diào)試的時(shí)候可能有用。
.exp:只有在編譯DLL的時(shí)候才會(huì)生成,記錄了DLL文件的一些信息,一般也沒有用。
.ncb:無編譯瀏覽文件(no compile browser)。當(dāng)自動(dòng)完成功能出問題時(shí)可以刪除此文件。編譯工程后回自動(dòng)生成。
??????????????????????????????????????????????????????????????????????????????????????????????????聲明:以上為從的個(gè)人初學(xué)時(shí)的學(xué)習(xí)筆記中整理制作而成,有不當(dāng)之處請(qǐng)自行更正.
?????????????????????????????????????????????????????????????????????∪∩BUG
??