一種窮人式的內(nèi)存泄露檢測方式
對(duì)于檢測程序代碼中的資源泄露問題,市面上已經(jīng)有很多工具了,但是今天我再來介紹一種新的方式,這種方式不需要安裝任何工具或者特定的編譯器開關(guān),也不需要第三方庫。
那就是:一直保持程序運(yùn)行,直到泄露的原因自動(dòng)水落石出。這是什么意思?
每日自動(dòng)壓力測試通常是工程開發(fā)中的一個(gè)常規(guī)部分。有一些軟件開發(fā)團(tuán)隊(duì)使用屏幕保護(hù)程序作為觸發(fā)器,其他團(tuán)隊(duì)使用自定義程序,還有一些團(tuán)隊(duì)需要手動(dòng)啟動(dòng)壓力測試,但無論如何,在你下班回到家后,你的計(jì)算機(jī)連接到測試服務(wù)器并接收一組整夜運(yùn)行的測試。
這些壓力測試經(jīng)常出現(xiàn)的一件事是這樣或那樣的內(nèi)存泄漏,由壓力測試團(tuán)隊(duì)識(shí)別,因?yàn)槌绦虻馁Y源使用率異常高。但是如何調(diào)試這些故障呢?這些機(jī)器沒有使用泄漏檢測工具運(yùn)行特殊的檢測版本,因此你無法使用它。
相反,你可以一種新的檢測思路:目標(biāo)運(yùn)行平臺(tái)有著豐富的資源環(huán)境(target-rich environment)。
假設(shè)你的程序正在泄漏內(nèi)存。連續(xù)大量使用十五小時(shí)后,程序開始出現(xiàn)內(nèi)存不足故障。你顯然在泄露一些東西,但是泄漏的具體是什么呢?
想想看:如果你泄露了一些東西,那么就會(huì)有很多。而你沒有泄漏的東西數(shù)量很少。因此,如果你隨機(jī)抓取進(jìn)程快照,它很可能是一個(gè)泄漏的物體!用數(shù)學(xué)術(shù)語來說,假設(shè)程序的正常內(nèi)存使用量為 15 MB,但由于某種原因,你已經(jīng)用完了 1693 MB 的動(dòng)態(tài)分配內(nèi)存。由于其中只有 15 兆字節(jié)是正常的內(nèi)存使用量,因此其他 1678 兆字節(jié)必須是泄漏的數(shù)據(jù)。如果從堆中轉(zhuǎn)儲(chǔ)隨機(jī)地址,則找到泄漏對(duì)象的可能性大于 99%。
因此,隨機(jī)抓取十幾個(gè)地址并轉(zhuǎn)儲(chǔ)它們。你很可能會(huì)一遍又一遍地看到相同的數(shù)據(jù)模式。那是程序的泄漏點(diǎn)。如果它是一個(gè)具有虛擬方法的C++對(duì)象,轉(zhuǎn)儲(chǔ) vtable 將快速識(shí)別它是什么類型的對(duì)象。如果是 POD(Plain Old Data) 類型,通??梢酝ㄟ^查找字符串緩沖區(qū)或指向其他數(shù)據(jù)的指針來識(shí)別它是什么。
最終結(jié)果可能會(huì)有所不同,但我發(fā)現(xiàn)這是一種非常成功的技術(shù),可以把它想象成一種精神力量。
總結(jié)
我一直在 Topomel Box 中使用一個(gè)外掛式的第三方庫來檢測內(nèi)存泄露,通過今天的文章,我明白了:我們可以什么也不做,就等它泄露,直至到達(dá)泄露原因是如此明顯的時(shí)間點(diǎn)。
正所謂:無為而無不為。