Q:WinDBG的Watch窗口中我想要查看長字符串,但是后面的內容都被省略為...了怎么辦?
A:如圖,雙擊你要查看的內容,出現光標后,移動光標即可查看后面被省略的內容
Q:WinDBG如何給程序設置命令行參數?
A:如圖,第一行是參數名(是我的一個用來測試的HTML文件名),第二行是參數所在的位置(也就是該HTML文件所在的目錄)
另外,第二行也代表程序運行時所在的目錄。什么意思呢?
比如說,在調試運行上面那個demo的時候,你把第一行留空(不給任何參數),但是第二行設置為c:\myfolder
你就會發現程序生成的文件在c:\myfolder之下,這就好像你打開了cmd,切換到c:\myfolder,然后再運行這個程序一樣的效果
---------------------------------------------------------------------------------------
最開始一直在擼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 # options 10 EHSC = /EHsc 11 COMPILATION_ONLY = /c 12 C_OUT = /Fo: 13 L_OUT = /OUT: 14 # compiler & linker debug option, to disable debug, replace '/Zi' & '/DEBUG' with empty strings 15 C_DEBUG = /Zi 16 L_DEBUG = /DEBUG 17 # targets 18 bin\test.exe: bin obj obj\main.obj 19 $(LINK) $(L_DEBUG) $(OBJ_PATH) $(L_OUT)bin\test.exe obj\main.obj 20 21 obj\main.obj: 22 $(CC) $(C_DEBUG) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) src\main.cpp $(C_OUT)obj\main.obj 23 24 # folders 25 26 obj: 27 mkdir obj 28 29 bin: 30 mkdir bin 31 32 # clean 33 # bin, obj folders and pdb files 34 35 .PHONY: clean 36 clean: 37 -rmdir /s /q bin 38 -rmdir /s /q obj 39 -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初步的學習就到這里。下面還會補充一些更進一步的例子。
附上zthreaddemo_debug的調試界面截圖,步驟跟上面一樣哦,試試吧!(注意,就算你設置了Source file path,WinDBG也不會自動去幫你打開cpp文件,所以在開始調試之前把需要的cpp文件打開,然后打上斷點!)
我修改了Makefile從而編譯的時候會保留調試信息,生成pdb文件(在Makefile中搜索L_DEBUG和C_DEBUG)