2009年7月2日 星期四

指標別亂用之型態轉換密室殺人案: sim-panalyzer 2.0.3 bug-fix log

拿到了新版的sim-panalyzer,但是BUG還是有的…
首先,參考 J.Whitham博士的網頁
把2.02版就存在的bug給修掉。

上述的BUG修完之後,還是會出現下面這個莫明奇妙的錯誤:

fatal: dio should be either odir or bidirBuffer type!

從字面上意思看來是說沒把 DIO 這個模組中 buffer type的參數設定好,
當然事情不會這麼簡單,不然全世界的工程師都回家種田了…

經過跟 GDB 一整個下午的搏鬥,發現:
出包的DIO這個資料結構所屬的 pspec->style 這個變數,
在程式剛開始時,是正確的的依照組態檔被設定成 bidir 列舉型態
但是程式開始執行沒多久(大約第三個指令)
就會被改成一個非常大的數字,大約就是 0xFFFFFFE8 這麼大…

程式一看已經超過列舉型態的上限,當然就吐了一行
dio should be either odir or bidirBuffer type!
的錯誤訊息,同時自動終止sim-panalyzer主程式。

但是原始碼中在讀入命令列參數去初始化pspec->style之後,
就沒有任何程式敘述會動到該變數了,
這不就是密室殺人案嗎?
現場沒兇器,但人死了,倒底是誰殺的?

進一步往回追,發現這個
pspec->style被不正常的篡改
很有可能是附近的另一個引數 pmwindex 因為某種緣故爆走的關係,
因為pspec->style被篡改的同時,
某個指標pmwindex為索引對某個記憶體位址作了寫入動作。
我們都知道指標是一種很恐怖的東西,
因為他賦予你在記憶體空間裡面隨地大小便、四處塗鴨的能力…
而有證人指出,案發當時的pmwindex
曾經從70左右的正常值爆增到 0xFFFFFFEF 這種天文數字,
很明顯的已經讓指標把位址指到某個他不該寫入的地方了

往回追 pmwindex的相關程式,
又發現另一個相關的變數 tstart也會有爆增的現像,
很好,兇手快出現了,仔細檢查tstart是怎麼被更改的,
終於,在 /libpanalyzer/io_panalyzer.c #273 附近,
發現了一個該打屁股的錯誤:

if((lat - plat - pspec->nctcycles) > 0)
tstart = now + lat - plat - pspec->nctcycles;

詐看之下很好很強大是吧? 沒什麼問題啊?
但是仔細的追查這些變數的資料型態,
發現lat, plat pspec->nctcycles這三個出現在IF敘述裡面的變數,
其型態都是 UNSIGNED !!

用減法比大小之前沒有作
型態轉換! 這就是兇手!
都已經是無號數了,不管怎麼作減法,都不會減出負數的!
所以這個if敘述就是 if(1) 永遠執行的意思…
吐血之餘把程式改成:

if(( (int)lat - (int)plat - (int)pspec->nctcycles) > 0)
tstart = now + lat - plat - pspec->nctcycles;

無厘頭錯誤消失,程式正常跑完…

奇妙的是同一個原始檔的另一處有一個一模一樣的錯誤,
但是被某位叫 Ludo的好心人修掉了:

#201
/* Ludo: added some casts here, since all variables are unsigned!
This solves some segmentation faults. */
if(((int)lat - (int)plat - (int)pspec->nctcycles) > 0)
// if((lat - plat - pspec->nctcycles) > 0)
tstart = now + lat - plat - pspec->nctcycles;

送佛也送上西天嘛~
還是這也是某種保護智財權的手段... 囧rz

結論:
1.使用c語言請隨時注意資料型態是否相容。
2.指標這東西威力強大,特別是在您需要密室殺人的時候,實為好用技倆。

1 則留言: