當前位置: 華文星空 > 知識

Bug往事(2)

2016-05-15知識

繼續說那些奇葩的Bug。

靠不住的系統元件:Vista和Speech Recogition

我們遊戲使用了語音辨識,使用了DirectX裏面的XAudio來采集聲音。Windows Vista裏面有一個語音辨識的元件,啟動那個程式,然後玩我們的遊戲,玩了一段時間,因為沒有使用麥克風,那個程式會自動關閉使用麥克風,然後我們的遊戲就Crash了。又是一個跨行程的奇葩Bug。

從現場來看,Crash在使用XAudio的庫程式碼裏面。看不出什麽線索,最後發現在日誌裏面,Crash前一會兒,XAudio的dll被Unload掉了。Vista那個語音元件很強悍,也會跨行程追殺大法,在自己行程把我的行程dll給Unload掉了。

雖然遇事先要懷疑自己的程式碼有問題,但這個情況太匪夷所思,所以我試圖推卸責任,我跑了幾個其他DirectX程式和Demo,但凡用到XAudio元件的,在Vista Speech Recognition這一大招前無一幸免,全部Crash。

問題不在我們這裏,但是作為一個職業殺蟲人,我有著「只解沙場為國死,何須bug裹屍還」的覺悟,決定還是要想辦法搞定它。

我猜這個元件結束的時候,廣播了點什麽訊息,讓系統所有行程去解除安裝這個Dll。我找了一個微軟提供的庫Detours Express,專做Hook API的勾當。它會反組譯API的入口程式碼,然後動態替換入口,插入jmp指令去執行我們自己的函式。先看了文件,搞懂這個東西怎麽用,然後猜測是一個OS內部的訊息導致Unload DLL,我們就攔截了RegisterWindowMessage。一通翻箱倒櫃,啥有意義的東西都沒發現。

再用spy++來攔截訊息,發現有一個MSUIM.msg.rpcsendreceive的訊息面目猙獰,很可疑。就在收到這個訊息以後,Dll就被Unload了。於是我們用Detours截住這個訊息,直接返回。

以為搞定了,但結果還是不行,有幾條別的訊息也會觸發Unload Dll,我一一用Detours攔截返回。攔截的訊息越來越多,看來不是個解決辦法。於是我懷疑我們沒有攔截到正確的訊息,懷疑OS啟動的時候便註冊了一堆內部用的訊息,而不是在執行行程的時候才註冊。那些訊息裏肯定有我想要的,我便異想天開地Hook了User32.dll,攔截下所有訊息,在安全模式下把修改過的user32.dll覆蓋原來的檔,然後滿懷希望的重新開機動Vista的時候。結果不出所料的藍屏了...User32.dll是凡人能隨便碰的嗎?這不是一個User friendly的庫,應該改名叫God32.dll。

這個bug搞了1周,最後才想到最基本的道理,說不定只是Dll內部參照計數被清掉了,所以系統就卸掉Dll了。當Vista語音元件Unload XAudio的時候,系統去看看XAudio庫有沒有什麽別人參照,結果發現居然沒有,那就順手清理了。就像地上有100塊錢,你東張西望,發現沒有人宣布擁有那張錢,沒有一點點猶豫,你隨手就把它放進了褲兜,進行了回收。嗯,就是這樣的,我喜歡比喻這種修辭手法。

理論上建立XAudio裝置的時候沒有做什麽額外的加Dll參照計數的事情,懷疑是MS的bug,建立D3D裝置、DInput裝置的時候都不需要做什麽特別的事情的,但他們的參照計數都沒有問題。

於是我惡搞了一下,在初始化XAudio完成以後,手動做了一次LoadLibrary,把XAudio2_1.dll強行Load一遍,相當於自行增加了參照計數。於是再無Crash。

從此我們的遊戲,在Vista 32上過上了幸福的生活。

可得結論:Vista靠不住

Takeaway: 不知道該說什麽了,這個bug太奇葩了。

效能的迷思

臨近最終版本釋出的時候,測試人員發現一個問題,當在Vista上連續打遊戲過7關以後,遊戲幀數一下子變成原來一半了。大家覺得很詭異,都不相信,之前整天玩遊戲都沒問題的,於是責令測試人員再重現幾次,否則拖出去刨坑埋了。我也沒當回事,

< style data-emotion-css="19xugg7"> .css-19xugg7{position:absolute;width:100%;bottom:0;background-image:linear-gradient(to bottom,transparent,#ffffff 50px);} < style data-emotion-css="12cv0pi"> .css-12cv0pi{box-sizing:border-box;margin:0;min-width:0;height:100px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:absolute;width:100%;bottom:0;background-image:linear-gradient(to bottom,transparent,#ffffff 50px);}
< style data-emotion-css="1pr2waf"> .css-1pr2waf{font-size:15px;color:#09408e;}
編輯於 2016-05-15 21:17
< style data-emotion-css="ch8ocw"> .css-ch8ocw{position:relative;display:inline-block;height:30px;padding:0 12px;font-size:14px;line-height:30px;color:#1772F6;vertical-align:top;border-radius:100px;background:rgba(23,114,246,0.1);}.css-ch8ocw:hover{background-color:rgba(23,114,246,0.15);}
< style data-emotion-css="1xlfegr"> .css-1xlfegr{background:transparent;box-shadow:none;} < style data-emotion-css="1gomreu"> .css-1gomreu{position:relative;display:inline-block;}
Bug