標籤:
最開始一直在擼JAVA,最近處於鞏固基礎和拓寬知識面的目的翻出了久違的C艸研究。習慣性的用IDE,要麼CODEBLOCKS,要麼VS.
過了一段時間,最明顯的感覺就是,IDE用多了很多細節不清楚,而這些細節往往是最關鍵的知識,關係到你能不能從根本上明白程式的本質或者完成一些頑固BUG的修複,而IDE往往會把這些東西給你屏蔽掉(出於方便和自動化的考慮),如果你不知道這些被屏蔽掉的細節,那麼你往往在構建程式的時候經常看到IDE報一大堆ERROR的時候不知所措
反正,我是終於明白了IDE不適合新手的原因。
在UNIX或者類UNIX系統下有GNU MAKE+GCC+GDB作為命令列編譯和調試的工具,個人喜歡稱之為3G套裝
那麼Windows下難道就只能依賴VS或者CODEBLOCKS+MinGW了麼,況且CODEBLOCKS+MinGW本質上也就是3G套裝。在Windows下開發一些東西的時候還是要MS自家的工具才吃得開
經過前段時間的學習,大概學習了一些MS家的NMAKE以及CL還有LINK的基本用法,見這篇隨筆
今天上網搜了搜,發現了神器WinDBG,終於不用在需要DEBUG的時候開啟笨重的VS了!新技能GET!MS套裝GET!(=,=‘‘‘逗比。。。)
點此下載教學PPT(我從百度文庫下載下來修改了一些微小的錯誤並上傳到我的網盤)
點此下載專案檔夾
代碼,main.cpp:
1 #include <stdlib.h> 2 #include <stdio.h> 3 4 char *getcharBuffer(); 5 void changeto4p(char* buffer); 6 7 int main() 8 { 9 system("pause");10 char *str = getcharBuffer();11 changeto4p(str);12 printf("%s",str);13 return 0;14 }15 16 char *getcharBuffer()17 {18 return "6969,3p3p";19 }20 21 void changeto4p(char* buffer)22 {23 while (*buffer) {24 if (*buffer == ‘3‘) {25 *buffer = ‘4‘;26 }27 ++buffer;28 }29 }
顯然,上面的代碼在changeto4p中嘗試修改read only的memory地區(25行),因此會發生Access violation error
首先,如果要調試你的代碼,那麼你在編譯的時候要給compiler還有linker都加上debug選項,這樣調試資訊(symbol,line number等等)才會保留下來給DEBUGGER
見Makefile:
1 # compiler 2 CC = cl 3 # linker 4 LINK = link 5 # libraries 6 LIB =
7 # headers 8 HEADER_PATH = /I include 9 # options10 EHSC = /EHsc11 COMPILATION_ONLY = /c12 C_OUT = /Fo:13 L_OUT = /OUT:14 # compiler & linker debug option, to disable debug, replace ‘/Zi‘ & ‘/DEBUG‘ with empty strings15 C_DEBUG = /Zi16 L_DEBUG = /DEBUG17 # targets18 bin\test.exe: bin obj obj\main.obj19 $(LINK) $(L_DEBUG) $(OBJ_PATH) $(L_OUT)bin\test.exe obj\main.obj20 21 obj\main.obj:22 $(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) src\main.cpp $(C_OUT)obj\main.obj23 24 # folders25 26 obj:27 mkdir obj28 29 bin:30 mkdir bin31 32 # clean33 # bin, obj folders and pdb files34 35 .PHONY: clean36 clean:37 -rmdir /s /q bin38 -rmdir /s /q obj39 -del *.pdb
我由於不是很會玩Makefile,所以DEBUG選項的添加或者刪除都是通過手工修改Makefile實現的。見第14行。至於CL和LINK的各個選項的含義,在MSDN可以找到,就不贅述了。
(說實話我覺得更好的辦法是一個target叫release,另一個叫debug,需要debug的時候就輸入nmake debug,所有的obj、exe、pdb檔案都放到debug\obj,debug\bin,debug\pdb三個檔案夾中,需要clean的時候就輸入nmake clean,nmake就直接產生release版本的obj和bin檔案夾,改天研究研究該怎麼寫這個Makefile)
開啟命令列,輸入nmake產生了demo\vc120.pdb, demo\bin\test.exe、demo\bin\test.pdb
這裡的vc120.pdb test.pdb就是調試資訊檔(Program Debug Database file),WinDBG用這些檔案找到原始碼的位置和行號還有符號的位置以及其他資訊
開啟WinDBG
第一步,選擇File>Symbol File Path,設定pdb檔案的位置為demo\bin,因為test.pdb在這個位置
第二步,選擇File>Source File Path,設定原始碼檔案的位置為demo\src,因為main.cpp在這個位置
第三步,選擇File>Open Executable,開啟test.exe
你會發現main.cpp也被開啟了(WinDBG根據test.pdb找到了main.cpp的位置)
第四步,打斷點,快速鍵為F9(命令為bp <代碼所在行的二進位地址>),我選擇給changeto4p這個函數打上一個斷點
第五步,開始調試,快速鍵為F5(命令為g,也就是go的意思,你也可以選擇按面板上的按鈕,如,基本的功能有:Go, Restart, Stop debugging, Break, Step into, Step over, Step out, Run to cursor, Insert or remove breakpoint, Command, Watch, Locals, Registers, Memory window, Call stack, Disassembly, etc)說白了就是(繼續運行,重新調試,停止調試,暫停,單步指令(跳入,跳過,跳出,運行到游標處),插入刪除斷點,命令視窗,變數觀察視窗,局部變數觀察視窗,寄存器觀察視窗,主存觀察視窗,調用棧,彙編代碼視窗等等),你也可以從View選項中找到這些功能。
對應的快速鍵可以開啟WinDBG去查看,我這裡就不手打了,擼不動,簡單說一下,F10是單步step over,F11是單步step into,跟VS裡面一樣
第六步,運行到changeto4p的時候,開啟Watch視窗,輸入*buffer,你會發現如所示,這裡的值是0n57 ‘9‘,什麼意思呢?0n的意思是十進位(類似0x表示十六進位,0開頭表示八進位),0n57 ‘9‘的意思就是字元‘9‘的ASCII碼是十進位的57,說白了就是*buffer的值是字元‘9‘。值得一提的是,這裡Watch視窗的name列不僅可以寫變數名,也可以寫合法的c++運算式,反正指標操作、結構體操作是可以作為合法運算式寫到name這一欄的,我估計簡單的算術運算式也是可以的,可以試試看。
另外:你可以選擇View>Locals查看局部變數,直接就能看到buffer字串的所有值,可以試試。
對於WinDBG初步的學習就到這裡。下面還會補充一些更進一步的例子。
Windows調試神器:WinDBG