關於解Bug的總結

來源:互聯網
上載者:User
1. 與其他應用互動的Bug
   背景:
    一個手機音樂播放器,多媒體通常存放在手機外部儲存卡上(SDcard上)。所以只有當SD卡Mount到手機上時,才可以播放媒體。音樂播放器就會監聽SD卡狀態,當SD卡從手上卸載或彈出時,播放器會儲存現場並停止播放;當SD卡重新Mount回手機時,再恢複現場和繼續播放。也即當播放器收到“SD卡Eject”訊息時,停止,當收到“SD卡Mount"時繼續播放。播放器可以在背景播放媒體。
    一個檔案管理工具是另外一個應用程式,可以用來編輯(如刪除)SD卡上的檔案。檔案發生變化後,這個第三方應用會發出”SD卡Mount“這樣的訊息,以便告知其他應用和系統,檔案發生了變化。
   問題:
    當播放器在背景播放媒體的時候,起動檔案管理工具,然後隨便刪除一個檔案(也可以是現正播放的媒體檔案),這時候,播放器停止播放媒體,並且當開啟播放器時,發現播放器是處於播放狀態的,但是卻沒有聲音。
   分析: 播放器不會沒有理由的去停止現正播放的媒體。尋找發現,播放器停止播放的原因有幾個:使用者請求停止,切換媒體時,SD卡Eject,SD卡Mount時。經過調試和追蹤記錄檔資訊,發現前面三種情況都未發生。那麼問題的原因就是SD卡Mount時,進行了恢複現場的操作,導致媒體停止了。那為什麼會進行恢複現場的操作呢,因為SD卡並未被Eject和Mount。進一步調試和追蹤記錄檔發現,當檔案管理工具刪除檔案後會發出“SD卡Mount”的訊息,以便告知其他應用檔案發生了變化。
   解決方案:
   當分析出了問題出現的原因,解決起來就容易了,只需要讓播放器在做恢複現場的動作前多一些檢測來保證,先前SD卡有Eject過,現在確實是SD卡Mount回來。否則,應該忽略這個訊息。
   教訓:
   這應該是軟體缺陷引起的Bug,音樂播放器本應該做這樣的條件檢查。音樂播放器本身的策略是沒有錯的,當沒有其他應用程式發出這樣的訊息時,它是完全可以正常工作的。這是一個典型的與其他應用或模組互動時產生的Bug。
   對於這類Bug,最重要的線索就是,當與其他應用一起操作時會出現問題。這個Bug比較簡單,因為很明確是與檔案管理工具有關。但在有些關係複雜的系統中,當出現了問題,很難搞清是表現問題的模組出了問題,還是其他模組出了問題。這就需要調試追蹤記錄檔,以縮小範圍。在調試的時候要一個一個模組的實驗和排除,以縮小範圍和進一點的深入調查。
2. 原因與問題離的很遠的Bug
   背景:
   一個模組專門負責處理SD卡上的多媒體檔案,解析這些檔案,擷取它們的元資訊,並存入到媒體資料庫中。它是由Java和C++以JNI方式組合來實現的。Java進行上層流程式控制制和寫入資料庫操作;C++負責解析檔案擷取檔案元資訊。它們之間通過JNI來通訊。
   問題:
   當處理一個特殊的檔案時候Java的JVM(虛擬機器)會異常退出(JVM abort),並列印出一條錯誤資訊:"JNI Warning: illegal start byte 0xb1".
   分析:
   這是一個很嚴重的錯誤,因為它會導致JVM崩潰,進程也會被核心殺掉。唯一的線索就是JVM崩潰時列印出的一條資訊"JNI Warning: illegal start byte 0xb1".通過搜尋這條訊息(幸虧有所有的原始碼),發現它是由JVM內部的CheckJNI.c檔案列印出來的。這個檔案是JVM中比較重要的一個檔案,它負責對JNI的所有參數進行合法性檢查。特別是字串。因為Java中用的是Modified UTF-8編碼格式,所以CheckJNI.c檔案就會對所傳進來的字串進行編碼檢查,如果字串不是一個合法的Modified UTF-8格式,就會發出警告並停止JVM。這裡找到了問題所在,是因為JVM檢查到了不合法的字串才導致JVM崩潰的。那麼不合法的字串是從哪裡來的呢?又是出現在哪個模組呢?因為系統中有無數地方在用到JNI,所以不能盲目的去尋找。又由於這是在媒體掃描器掃描某個媒體時候出現的,因此主要目標鎖定在媒體掃描器的JNI部分。媒體掃描器的C++部分解析多媒體檔案,然後把所得到的結果(通常為字串)通過JNI傳回給Java層。問題就很有可能出在這裡,因為多媒體檔案的資訊有多種編碼格式,其中元資訊就有可能是非法的Modified UTF-8編碼格式。經過調試跟蹤,發現,確實是這裡出現了問題。
   解決方案:
   這個問題的解決方案仍不是很好,一種方法是對其進行編碼轉換,但這要知道字串原來的編碼方式。另一咱簡單的方法就是在傳給JNI之前做一次編碼合法性檢查,以過濾到不合法的字串。最後,採用了後一方式解決了這個問題。
   教訓:
   首先,系統崩潰時所給出的資訊和出錯時給出的資訊是第一重要的線索,雖然它們可能不是問題真正的原因,但是從它們出發就可以追蹤到原因。其次,錯誤資訊,是由代碼列印出來的,所以當你不知道是哪個模組出錯時,可以用錯誤資訊對源碼進行局搜尋,就可以定位出模組和源碼位置。最後,如果是一系列的原因導致了一問題,那麼可以在最源頭解,也可以其中的某一個環節來解,只要不會導致程式崩潰即可。
3. null 指標異常NullPointerException
   背景:
   在C/C++/Java中null 指標異常是比較常見的一類導致程式崩潰的原因。在C/C++/Java中,如果使用的指標或對象沒有正確的初始化,則很容易發生NullPointerException。
   問題:
   當發生NullPointerException的時候,程式通常會因異常而崩潰的。但通常都會列印出運行時的堆棧資訊。
   分析:
   從程式的堆棧資訊,會很容易的看到發生問題的代碼位置,這樣就可以找到直接原因。但是這找到問題的一小部分,具體是什麼導致對象為空白,這就不是那麼容易調查出原因了。
   解決方案:
   對於這類問題,一開始能想到的辦法就是加上對null 指標的檢測,如果指標或對象為空白的話就不對其進行操作。但這是行不通的,這也不是正確的解決方案,最直接的問題就是,當指標為空白的時候應該去做什麼。如果在一個類中,在其他地方引用的時候都做了null 指標檢測,而這個地方沒有做,那麼可以仿照其他地方那樣,加上null 指標檢測。但假如不是這樣的情況,就要好好的調查一下指標為什麼會是空,而非處理null 指標。但這通常都是比較困難的,因為要去追蹤對象是從哪裡來的,又在哪裡被修改和引用,是在哪裡初始化的。只有找到了真正讓對象為空白的原因,才能算是比較完整的解決了問題。但如果一個比較複雜的系統,引用的地方很多,且假如又涉及到多線程時,則追蹤起來會更加的困難。
   教訓:
   對於null 指標問題,不能簡單的加上一個條件。要進一步的深入去調查是什麼導致了指標為空白。除非,你有充足的理由去加上條件。
4. 無解的問題
   案例一:
   背景:
   有些問題是極及詭異的,而且出現的機率非常的小,但它們還是會出現,但是找不到合適的解決方案。
   問題:
   在一個GUI系統中,在一個比較基礎的類裡面報出了一個NullPointerException。由於這個類會被很所有涉及GUI的應用程式所使用。
   分析:
   根據程式退出時列印出來的堆棧資訊,找到了發生異常的代碼位置。令人感到驚訝的是,這一行是絕不可能發生null 指標的,因為它用的都是基礎資料型別 (Elementary Data Type)。上下幾十行之內也是絕不可能發生NullPointer的。
   解決方案:
   這個問題,始終沒有找到解決方案。
   案例二:
   背景:
   對一個系統做大規模的隨機壓力測試。一個對象的類Message是一個final的類,且其重載了toString()方法,它會按如下格式列印資訊:"{ what=XXX when=XXX XXXXXX }"
   問題:
   在一次測試過程中,系統核心進程因異常退出,導致系統自動重啟。
   分析:
   問題的原因是在核心進程中發生了一個RuntimeException,並有一條訊息:"[c0x44bc: This message is already in use."。從堆棧找到退出的位置的代碼,發現它是程式檢測到不合理的操作然後拋出的一個RuntimeException:代碼如下:
         // ...
     if (msg.when != 0) {
             throw new RuntimeException(msg + " This message is already in use.");
         }
         // ...
   這裡的msg是一個Message的對象。
   通常來講+會調用對象的toString()方法,而toString()方法的輸出又有特定的格式,所以,這裡就發生了讓人極其迷惑的事情。因為最終列印出來的訊息跟對象的toString()有很大的差別。從日誌資訊來看,當前對象應該是一個char數組,而並非一個Message對象,但是在相關的上下文都無法找到這樣一個char數組。
   解決方案:
   這個問題,懷疑是對象的記憶體已被破壞,其內的資料已不再是對象本身。這也是一個沒有解決方案的問題。
   教訓:
   這類問題是真正的難題。需要對語言和系統達到精通的人物才可能解的了。
5. 難重現的必現問題
   背景:
   一個Gallery應用程式能夠以網格形式顯示很多張圖片。當圖片較多時,就會在左邊出現滑塊用來滾動螢幕。正常來講,當開啟應用時,這個滑塊應處在最上面的位置。
   問題:
   有人報告說初始開啟應用時,滑塊不是在最上面,而是在中部,或其他地方。而且聲稱這是必現的問題。
   分析:
   但當調試的時候卻怎麼也無法重現這個問題。雖然這並不是一個嚴重的問題,但感覺這樣的行為是很詭異的。在調試的過程中,發現,測試人員的應用與我這邊應用顯示圖片的順序似乎有些不同,是正好相反的順序。這是有一個可配置的選項在控制的,所選項設定為正序或倒序。發現測試人員當時用的倒序,而通常大多數情況下,用的都是正序(可能是因為沒有人去設定這個東西,它預設的是正序)。這可能是問題產生的原因。果然,當把順序設定為倒序的時候,滑塊的位置就不會置頂了。
   解決方案:
   找到了問題的重現規律,對於這種問題就好辦了。發現,當設定為倒序的時候,代碼的本意是想把滑塊放在最後,但是計算時有些錯誤,誤把一個螢幕視窗的高度當成整個文檔長度了。所以當,整個文檔長度超過一個螢幕時,滑塊的位置就不正確了。由於,把滑塊放在最上端的更符合一般情況,所以就無論排序次序,把滑塊置頂。
   教訓:
   事實上,很少問題是真正的小機率事件(Seldom),只有當涉及多個線程的時候才會有真正Seldom的問題,因為無法確定線程的執行順序。對於其他的問題,應該是都還沒有找到重現的規律。相信了這一個事實以後,就要不斷的去實驗和假設以重現問題。在實驗的時候,也要注意細節,因為很多細節都可能是一條重要線索。最重要的是要相信問題是存在的,是可以重現的,更是可以解決的。
   有一些方法技巧可以用來重現看似比較難重現的問題:
      1. 仔細詢問或查看問題出現時的相關操作和日誌,以確定是否漏掉了一些必要的前提條件和操作
      2. 如果涉及與其他應用或模組互動,則要瞭解每個應用和模組的特性,然後做適當的假設,再去做實驗。
      3. 猜測可能導致問題的原因,然後去創造這些條件,看在有這些條件的情況下,是否可以重現問題。比如,如果猜測是時間長短或檔案大小導致了問題,那麼就可以調大時間,用大檔案來測試。如果猜測是null 指標的問題,那麼就可以故意創造出一個null 指標等等。
      4. 要相信問題是存在的,也要相信問題是可以重現的,更要相信這個問題是可以修複的。
      5. 要有耐心,不斷的思考,假設,然後去驗證,一次改變一個條件,一點一點的分析與驗證,最終是能夠重現並修改問題的。
6. 真正難重現的問題----線程問題
   背景:一個手機音樂播放器支援多個播放清單,當刪除播放清單的時候,如果其中有現正播放的歌曲,那麼當刪除這個播放清單後,是不會再繼續播放。在刪除過程中,如果刪除到現正播放的歌曲時,會開啟並播放播放清單中的下一個歌曲,直到播放清單中的所有歌曲都刪除完。刪除歌曲的動作是放在與播放不同的線程。
   問題:有些時候,刪除含有現正播放歌曲的播放清單後,當前歌曲跳到了其他播放清單繼續播放
   分析:刪除過程中會涉及到很多個過程:停止,找到下一首,播放,和刪除,如果每一次都這麼走的話,是不可能出現這個問題的。經過大量的調試與跟蹤,最終發現,是由於停止和播放沒能一次執行完,中途被打斷。因為刪除是在另一個線程中,因此有可能當正在執行停止的時候,TaskScheduler切換了線程,執行了播放,從而切換到了另外的播放清單。
   解決方案:找到了問題的原因,解決起來就很容易了,加上同步鎖,讓刪除,停止和播放的每一個過程都保證不被中斷,就解決了這個問題。
   教訓:這是一個真正的隨機出現的問題,因為它是由於線程引起的。多線程帶來的第一個問題就是不確定性,另外一個問題就是同步與共用的問題。如果沒能很好的處理同步與共用,那麼多線程會帶來更多的問題,遠多於它們所解決的問題。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.