下面有從淺入深的6個問題,您可以嘗試回答一下
問題1,2
這兩個問題最簡單,我在一個例子里說明
例如如下循環(huán)
for(inti=0;i<1000;i++){doSomeThing......}
在循環(huán)的大括號上單擊右鍵,插入斷點,用這個方法,可以對付那些喜歡把語句寫在一行上的家伙,其實,隨著.Net3.5中Linq的出現(xiàn),我們肯定也會經(jīng)常在在一行上寫復(fù)雜的表達式,這個時候用這種插入方法會比較管用
ok,現(xiàn)在我們來編輯這個斷點的條件,在斷點上右鍵單擊,選擇如圖菜單項
在彈出的窗口中可以設(shè)置斷點命中的條件i==900
注意我是在調(diào)試C#代碼,默認(rèn)的條件語句語法是C#,如果你想切換,那就需要用Ctrl-B,來插入斷點,并在彈出窗口中選擇語言
通過這樣設(shè)置條件斷點,我們就可以解決我們的問題1,2了
問題3
你有一個表達式在上面循環(huán)的某一次發(fā)生了變化,你想知道是哪一次,在哪個地方,怎么才能做到?
同樣通過設(shè)置條件斷點我們還可以解決我們的問題3,對表達式變化的跟蹤
string user="yizhu2000"
for(int i=0;i<10000;i++){
DoSomething1()
.......
DoSomethingN()
}
當(dāng)循環(huán)執(zhí)行完畢時我們發(fā)現(xiàn)user變成了"smart_boy",你不知道這個值是在第幾次循環(huán)的時候變化的,那么你是不是會選擇打上斷點,一次一次中斷,來查看呢?當(dāng)然不用
在循環(huán)體結(jié)束的位置我們設(shè)置一個斷點,打開條件編輯窗口(打開方法同上),設(shè)置表達式為user,勾選下面的HasChanged,也就是說,你告訴斷點,當(dāng)user的值發(fā)生變化時才觸發(fā)
(注意:第一次執(zhí)行到斷點的時候,程序一定會中斷,并計算這時表達式的值,所以,所謂發(fā)生變化,指的是以后執(zhí)行到斷點是表達式的值和第一次執(zhí)行到斷點時表達式的值的比較)
問題4
你希望你的斷點在被命中100次后,每命中三次中斷一次,比如第103,第106,第109怎樣做?
如何讓斷點在指定的命中次數(shù)或者大于某個次數(shù)時觸發(fā)呢?方法是設(shè)定幾個斷點的HitCount,右鍵單擊斷點,在彈出菜單中選擇Hit Count,會彈出如下窗口
在"when the break point ishit"下拉列表里,我們可以看到四個選項
break always:總是中斷
break when the hit count is equalto:等于某次數(shù)時中斷
beak when the hit count is a multpileof:當(dāng)次數(shù)是某數(shù)的倍數(shù)時中斷
break when the hit count is greater than orequal to:當(dāng)大于等于某數(shù)時中斷
問題5
你有在調(diào)試一個服務(wù)程序,希望在其內(nèi)部打上了斷點,可是,由于這是一個公用的服務(wù)你不希望其他訪問這個服務(wù)的程序被你的調(diào)試所干擾,你想怎么辦?
前面4個問題都已經(jīng)解決了,第5個問題的解決方法是利用斷點的Filter功能,比如我希望斷點只有被機器名為yizhu的機器訪問才能觸發(fā),我可以這樣設(shè)置
當(dāng)其他機器訪問程序的時候,斷點將不會觸發(fā),這樣做的優(yōu)點是通過設(shè)置機器名,我們可以讓其他機器訪問的時候感覺不到斷點的存在,除此之外我們可以設(shè)置機器名,進程號,進程名,線程號,線程名作為filter,而且還可以把他們組合起來,比如我希望通過當(dāng)機器yizhu的dllhost進程調(diào)用時才觸發(fā),那么問題就可以設(shè)置為MachineName="yizhu"&ProcessName="dllhost"
問題6 怎樣知道2個斷點中斷的時間間隔
現(xiàn)在我們來解決第6個問題:
在程序性能調(diào)試的時候,我們經(jīng)常需要知道某段代碼的執(zhí)行效率,一般來說,我們可以在程序中加入時間點,通過時間點相減來取得時間間隔,這種方法有個顯而易見的缺點就是需要修改程序,想要不修改程序,就需要借助一些工具,那么有沒有什么方法可以聲明式的插入時間點,并計算值呢?其實斷點完全可以做到
在給出方法前,我們來看看斷點的另外一個設(shè)置項,When Hit,這個選項可以
我們輸出了變量user的值,下面ContinueExecution表示程序不會中斷,輸出后繼續(xù)執(zhí)行,注意表達式需要用{}括起來,,其他的部分會被作為字符串輸出。設(shè)定WhenHit后斷點變成了方形(看厭了圓斷點,我還挺喜歡這個方家伙的)
在output中查看輸出結(jié)果,如下:
既然可以計算表達式,我們的第一個最簡方案就出來了,也就是在程序執(zhí)行到斷點的時候,輸出DateTime.Now,這樣當(dāng)然是可行的,但是我們需要的是時間間隔,所以我們還需要自己來算個減法,還是挺麻煩的,怎么樣才能讓程序自己輸出時間間隔呢?有一個想法是這樣的,我們在上一個斷點聲明一個時間變量,然后在下面的斷點里用DataTime.Now減去這個變量,即
斷點一的條件:{DateTime _t=DateTime.Now;}
斷點二的條件:{DateTime.Now-t;}
看起來不錯,但是實際運行時就有問題了,讓我們看看輸出吧
上面高亮的部分說,變量申明只能在immediatewindow中進行,所以斷點一的變量沒有申明成功,關(guān)于immediatewindow,我們以后會涉獵到,反正就是說想在表達式里申明變量,沒門,死路一條.那么我們怎么才能不申明變量又時間點呢?
這時我想起了Thread.SetData方法,這個方法可以往當(dāng)前線程專門提供的空間中插入一些數(shù)據(jù),并且可以通過GetData得到數(shù)據(jù),具體細節(jié)參考
http://msdn2.microsoft.com/zh-cn/library/system.threading.thread.setdata(VS.80).aspx
于是方案就有了,在第一個斷點處把時間放入Thread的DataSlot,然后第二個斷點取出來相減
斷點一的條件:{Thread.SetData(Thread.GetNamedDataSlot("ExecutionTime"),DateTime.Now);}
斷點二的條件:{DateTime.Now-(DateTime)System.Threading.Thread.GetData(System.Threading.Thread.GetNamedDataSlot("ExecutionTime"));}
看看輸出效果
我們的目的已經(jīng)達到了,output中成功的輸出了時間間隔,當(dāng)然,還不是很完善,首先,這個方法限于兩個斷點,你想多打幾個斷點,測試兩兩間的間隔還是比較麻煩.測量精度也可以提高,大家有興趣可以自己研究這個方法的擴展
==================================
王偉冰
=============================================
Visual Studio 調(diào)試(Debug)小技巧
http://hi.baidu.com/liudong/blog/item/d0434c08c6d315970b7b827e.html
在Visual Studio 運行調(diào)試過程中,有兩個非常有用的小工具:
1,Command Window。
2,Immediate Window。
Command Window用于執(zhí)行一些有用的命令。例如創(chuàng)建一個新文件可以使用命令:
File.NewFile "abc.cpp"
有趣的是提供一個和Dos中cls類似命令。
ImmediateWindow提供在調(diào)試過程中運行一些有用的表達式,或者查看程序中的變量的值。例如程序中有兩個變量a和b,現(xiàn)在要測試a+b的值,可以使用下面的命令(注意前面的>不可省略):
>Debug.Print a + b
MSDN參考:
ms-help://MS.MSDNQTR.v90.en/dv_vscmds/html/48711628-1909-4713-a73e-d7b714c77f8a.htm
ms-help://MS.MSDNQTR.v90.en/dv_vscmds/html/d33e7937-73f3-4c69-9df0-777a8713c6f2.htm
====================================
Visual Studio2008環(huán)境與VC6.0的環(huán)境存在著比較大的區(qū)別,下面就一些小小的區(qū)別在這里做一些探討,歡迎指教!
1、如果是調(diào)試控制臺程序,很多時候點擊“啟動調(diào)試”后是一閃而過,此時可有兩種方法讓cmd下dos調(diào)試屏幕暫停:
A:不要直接點擊vs2008的“啟動調(diào)試”按鈕,而是按Control+F5組合鍵。
B:在主函數(shù)main()里“return 0;”前加上兩句:cin.get();樣式如下
eg: int main()
2、類、函數(shù)和變量是C++編譯器的標(biāo)準(zhǔn)組件,它們都放置在名稱空間std中(此時頭文件沒有后綴名h)。在vs2008C++下,如果不包含using namespace std;指令,那么必須使用std::前綴,如
#include "stdafx.h"
#include<iostream>
void simon(int); //函數(shù)原型
//using namespacestd;
int _tmain(int argc, _TCHAR* argv[])
{
simon(3);
std::cout<<"請輸入一個整數(shù): ";//必須使用std::前綴,以下都是
int count;
std::cin>>count;
simon(count);
std::cout<<"完成!"<<std::endl;
std::cin.get();//這兩行是使調(diào)試屏幕暫停,不會一閃而過
std::cin.get();//讓程序等待鍵擊
return 0;//退出主函數(shù)
}
void simon(int n) //自定義函數(shù)
{
std::cout<<"現(xiàn)在整數(shù)是"<<n<<"測試!"<<std::endl;
}
下面是一個使用using namespace std;名稱空間的對比:
#include "stdafx.h"
#include<iostream>
void simon(int);
using namespace std; //這是一個使用std;名稱空間的例子
int _tmain(int argc, _TCHAR* argv[])
{
simon(3);
cout<<"請輸入一個整數(shù): ";
int count;
cin>>count;
simon(count);
cout<<"完成!"<<endl;
cin.get();
cin.get();
return 0;
}
void simon(int n)
{
cout<<"現(xiàn)在整數(shù)是:"<<n<<"測試!"<<endl;
}
還有一種方法,就是既不使用std;名稱空間,也不使用std::前綴,而是使用using編譯指令。如:
#include "stdafx.h"
#include<iostream>
using std::cout; //直接使用using指令
using std::cin;
using std::endl;
void simon(int);
//using namespace std; //這是一個既沒有使用std;名稱空間也沒有使用std::前綴的例子
int _tmain(int argc, _TCHAR* argv[])
{
simon(3);
cout<<"請輸入一個整數(shù): ";
int count;
cin>>count;
simon(count);
cout<<"完成!"<<endl;
cin.get();
cin.get();
return 0;
}
void simon(int n)
{
cout<<"現(xiàn)在整數(shù)是:"<<n<<"測試!"<<endl;
}
===========================