閱讀685 返回首頁    go 技術社區[雲棲]


調試

都知道發燒不是因為額頭被熱水燙過,肚子疼通常也不會是因為肚子受傷.其實調程序也是如此.
找錯誤的時候不該隻從錯誤的地方區找,有可能在遙遠的地方的問題,導致了這裏的錯誤.
也不要去相信那些從來沒出過錯的地方,就是不會錯的,從來不錯隻表示它過去沒錯,不表示現在也是對的.

今天一個同事的程序就遇到這個問題,一個自定義表格控件,用了很久了,突然今天發現在一個窗體上操作著操作著就綁不出來數據.
重新進入窗體又可以了,鬱悶了很久,單步調試了幾個小時(因為不知道怎麼重現這個錯誤,反正就是"某些操作"以後會錯),把所有的
代碼邏輯都過了好多次,可是就是找不出錯在哪,隻知道就是在某些地方經過以後,就再也不可能出來數據了.

晚上沒轍了,明天要用的,就這個地方過不去,於是扔給我幫忙. 我重複操作幾次,掌握到大致的出錯地方,然後就在重點區域,如綁定操作
的附近設了斷點,運行了幾次次,發現代碼沒有錯,Sql語句返回正確,表格綁定方法也沒有問題,返回true,就是數據再也不出來.

觀察到表格的腳部對數據的條數統計是正確的,隻是上麵不顯示數據. 監視了表格控件的一些主要的屬性,意外地發現,表格中表示
當前頁索引的屬性值是-1,顯然這是問題所在,搜索了一下,發現窗體中沒有對這個屬性賦值的操作.那-1又是怎麼來的? 重新進入窗體
屬性值出現正確的0,然後做會改變這個值的操作(翻頁,在表格組件內部實現) 發現都正常,然後再嚐試那些有可能產生錯誤的操作,
試了好幾次,終於有一個地方,操作以後變成了-1,-1以後就永遠-1了. 當一個操作導致表格中沒有數據的時候,表格的頁索引就變成-1
腦海中馬上明白發生了什麼事了,bug在表格控件內部.  馬上也猜出產生這個錯誤的原因. 原來表格本身保持了這個屬性的狀態,這樣
在多次綁定數據的時候,如果第一次綁定了N頁,第二次綁定了M頁(N>M+1),並且在第一次綁定以後,翻到了第P頁(N>P>M),那麼在第2次
綁定的時候這個狀態依然是P,而實際上數據卻並沒有那麼多,會拋出NullReferenceException的異常,於是猜測表格控件的設計者考慮到這個情況,
於是,對此做了處理,當遇到這個情況時強製令 P=M-1 (因為一個索引是0開始,一個是1開始,所以-1). 但是他卻忽略了同時M=0的情況.
在M=0的時候,P就出現了-1 .由於這個第-1頁是沒有意義的,也是原控件設計者所沒有考慮到的情況. 就發生了上述那些奇怪的總數
統計正常,而數據不顯示(因為根本不存在第-1頁的數據),由於上麵沒有數據,又引起了翻頁功能的不可用,因此也不可能把這個-1
給修改回來,於是就不管怎麼綁數據,怎麼操作,都一直-1下去了...

反編譯了原控件,從IL中證實了我的猜測完全和實際情況一致. 於是解決問題就變成非常簡單了.

另外有一點,控件中對一些異常,有必要throw出來給外麵一層,雖然說如果外麵沒有處理會造成程序崩潰,但是要是把所有沒有意料到
的異常都用一個空的catch塊把它殺死在控件內部,其實更加危險,造成程序的不可預料性,而且又難以查找.所以這裏有一個平衡的問題.
這還是看設計者的經驗,具體問題具體分析.

最後更新:2017-04-02 00:00:28

  上一篇:go 論項目的倒掉
  下一篇:go Windows 核心編程研究係列之二:讀取指定物理內存地址中的內容