1.當你發現有一個東西應該要啟動而沒啟動時,先去找看看當初的啟動條件,
如果啟動條件是一個函式如IsEnable();則trace進去這個函式,一直追下去。
2.善用OutputDebugString(),尤其是當你要對付一大堆的AI或事件。例如當你
要找出某個莫名奇妙快速位移的AI時,就先用下列的方式print出來所有的AI
位移量:
char msg[128];
sprintf_s(msg, "AI:%d distance %.3f\n", m_iAIID, fDist );
OutputDebugString( buf );
如果你已經確定某一個AI是位移特別快的,可以在你的程式碼中加上:
if(m_iAIID == 12345678)
{
int I = 0;
}
這樣的程式碼,並在int I = 0;加上break point來方便你直接找到要trace的AI
而不用對所有的AI一個個按F10或F5慢慢找。但要注意一件事,使用OutputDebusString
會導致程式變慢,有些要高速framerate才會出來的bug可以考慮改將error message寫到記憶體中。
3.善用data break point,對付一些應該有值的資料卻變成0X0時,可以用data break point
在該data有值時下一個data break point,但要在debug mode執行時。例如g_Device本來
一create時為0x12345678,卻在執行幾個frame後變成0x0。你便可以在g_Device一create後
做一個data break point去鎖住g_Device的值,當它一改變時你就可以知道是誰動了它。
4.多看memory。有的時候會出現資料明明就給對了,但寫到字串後卻有問題,這時候可以看看記憶體
的資訊,有可能會發現是一些字串沒接NULL結尾或是把ASCII當作UNICODE之類的問題。
5.確定問題在哪裡。有的問題是出現在程式上,有的問題是data。當我們發現上一個版本OK這個版
本卻不行時,先確定兩個版本的差異在哪裡?如果是美術資料有問題,要確定問題是因為格式錯誤
還是他們超出規格?倘若是程式方面的問題,請找出sourcesafe來比對程式碼的差異。
6.簡化除錯環境。如果碰到一些畫面上不知道是引擎還是我們程式的問題時,可以改寫demo來
試試看,如果在Demo也有問題就可能是那些改寫的程式碼有誤或資料的問題,反之則要找看看我們自
己的程式。
另一個簡化除錯環境的方式是將不需要的程式碼先拿掉,例如只要測AI時就先把特效都關掉,如果這樣就
不會當的話可能就是特效有問題。要做到這一點必須要使用每個功能前先檢查該功能是否存在:
if(m_AIManager)
{
//…………
//AI的update
//
}
這樣的方式來寫,也就是說我們就可以直接不create m_AIManager來關掉這個功能。
7.在Profile或Release版有時會當在無法確定的位置,這時可以利用OutputDebugString的方式來縮小追查
的範圍。例如以下的程式我們無法確定當在哪裡時:
....
a->Do();
b->Do();
c->Do();
....
這時可以加上一些除錯訊息:
....
OutputDebugString("Begin a->Do()\n");
a->Do();
OutputDebugString("Begin b->Do()\n");
b->Do();
OutputDebugString("Begin c->Do()\n");
c->Do();
OutputDebugString("End all\n");
....
如果接下來當掉了最後的訊息是Begin c->Do()就可以判定是在c->Do()這裡出的問題,然後在此函式中再繼
續找問題。
要注意的是,這樣的除錯方式在multi-thread時不見得都會正確,因為在thread1當掉可能會在thread2中
顯示Begin c->Do()而誤判為c->do()的問題。
此篇文章感謝史董的協助