這兩天一直在研究一個(gè)Crash問(wèn)題,其表現(xiàn)非常明顯就是Memory Heap被破壞了,但是由于破壞堆的現(xiàn)場(chǎng)無(wú)法準(zhǔn)確定位,發(fā)生Crash的地方已經(jīng)不是現(xiàn)場(chǎng),所以一直都沒(méi)找到原因。最后只好將代碼Roll Back回去,一個(gè)一個(gè)模塊的試,最終發(fā)現(xiàn)問(wèn)題出現(xiàn)在某一個(gè)模塊中指針類型的強(qiáng)制轉(zhuǎn)換引起的虛函數(shù)調(diào)用錯(cuò)誤上。
錯(cuò)誤是這樣的,有一個(gè)指針是A類型的,被強(qiáng)制轉(zhuǎn)換為B類型,并且通過(guò)B類型調(diào)用B的虛函數(shù),但是實(shí)際上調(diào)用的虛函數(shù)地址在A的虛函數(shù)表中。由于兩者參數(shù)并不相同,所以導(dǎo)致錯(cuò)誤出現(xiàn)。
B類型的函數(shù)參數(shù)中有一個(gè)std::vector類型,由于c++遵循cdecl調(diào)用約定,所以是由被調(diào)用端負(fù)責(zé)清理堆棧,這時(shí)候就會(huì)調(diào)用std::vector的析構(gòu)函數(shù),而實(shí)際上該參數(shù)已經(jīng)在調(diào)用A的虛函數(shù)時(shí)被破壞了,在執(zhí)行完這個(gè)函數(shù)之后,棧是正確的,但是堆已經(jīng)被std::vector的析構(gòu)函數(shù)破壞,所以出現(xiàn)了heap Corruption的錯(cuò)誤。
Heap Corruption是C++開(kāi)發(fā)中非常棘手的一個(gè)問(wèn)題,其引起的Crash有兩點(diǎn)非常難以琢磨:
1. 在Debug版較難或者不出現(xiàn),在Release版常常出現(xiàn)
2. 在Release版本上也是在非現(xiàn)場(chǎng)出現(xiàn),而且往往在大量釋放內(nèi)存的地方出現(xiàn)。
相信應(yīng)該有比較好C++的Heap Corruption工具,BoundChecker曾經(jīng)用過(guò),可惜太復(fù)雜不會(huì)用,不知道有沒(méi)有非常有效的檢測(cè)Heap Corruption工具。