雜想之一個(gè)C++內(nèi)存泄露案例
最近正好有個(gè)內(nèi)存泄露分析的案例,和大家分享下,其帶給我的一些思考。
開(kāi)發(fā)模型與問(wèn)題發(fā)現(xiàn)的時(shí)機(jī)
在研究(Research)階段,做好充分的學(xué)習(xí)和驗(yàn)證,要當(dāng)問(wèn)題追蹤(Trouble Shooting)一樣的細(xì)心,不放過(guò)任何的蛛絲馬跡,尤其是那些想當(dāng)然的場(chǎng)景,最后也許是讓你出乎意料的地方。要做到
明確需求,廣泛閱讀相關(guān)關(guān)資料與有相關(guān)經(jīng)驗(yàn)的人員謙虛溝通學(xué)習(xí),做代碼級(jí)別的驗(yàn)證,并且不放過(guò)蛛絲馬跡,還需要及時(shí)和相關(guān)組員匯報(bào)和討論相關(guān)研究進(jìn)展,發(fā)現(xiàn)可能的問(wèn)題和應(yīng)對(duì)方案。在設(shè)計(jì)過(guò)程中,要做到詳細(xì)設(shè)計(jì),盡量考慮到多種可能的場(chǎng)景,測(cè)試以及部署相關(guān)的。一般相關(guān)的人員(比如QA)或者預(yù)備人員,在參與會(huì)議過(guò)程中,要盡可能的認(rèn)真聆聽(tīng),盡量給出自己的建議和想法,讓設(shè)計(jì)方面的問(wèn)題及早地暴露。
開(kāi)發(fā)過(guò)程中,開(kāi)發(fā)人員要不斷的提高自己的編碼能力(比如熟知一些C++常見(jiàn)的避坑寫(xiě)法),做好單元測(cè)試,并且在編寫(xiě)代碼的時(shí)候,筆者也經(jīng)常有一些疑問(wèn)或者感覺(jué)某個(gè)地方未來(lái)可能會(huì)產(chǎn)生問(wèn)題的(根據(jù)墨菲定律,那一定會(huì)產(chǎn)生問(wèn)題),可以用筆記將其記錄下來(lái),或者本人比較喜歡用微軟的
To Do(以前叫做Wunder List)去進(jìn)行記錄, 然后在有空閑時(shí)間的時(shí)候,對(duì)這些問(wèn)題進(jìn)行仔細(xì)查看和測(cè)試。代碼Review。大家都知道代碼review的重要性,然而在項(xiàng)目進(jìn)行時(shí),卻往往沒(méi)有給代碼Review騰出足夠時(shí)間。那么在一些功能測(cè)試很難暴露的問(wèn)題,比如內(nèi)存泄露,內(nèi)存破壞,UAF(Use After Free, 使用釋放后的內(nèi)存)等問(wèn)題, 在代碼Review過(guò)程中也許會(huì)被發(fā)現(xiàn)。
CI/CD中,集成自動(dòng)化的相關(guān)測(cè)試,比如單元測(cè)試(Unit Test),接口測(cè)試(Interface Test),集成測(cè)試(Integration Test),驗(yàn)收測(cè)試(User Acceptance Test), 以及壓力測(cè)試(Stress Test)。像本文所說(shuō)的內(nèi)存泄露問(wèn)題,應(yīng)該在持續(xù)的壓力測(cè)試過(guò)程中很可能會(huì)暴露出來(lái)。那這樣只要RD在開(kāi)發(fā)完代碼提交到代碼倉(cāng)庫(kù),觸發(fā)了CI/CD后,便可以自動(dòng)獲取測(cè)試報(bào)告,發(fā)現(xiàn)可疑的問(wèn)題。
如果不能在自動(dòng)化階段完成這些測(cè)試,那么在RD在進(jìn)行開(kāi)發(fā)的過(guò)程中,RD和QA可以共同準(zhǔn)備壓力測(cè)試的方法和腳本,便于在盡早的時(shí)候進(jìn)行測(cè)試,暴露問(wèn)題。

內(nèi)存泄露的發(fā)現(xiàn)與分析方法
如果上一個(gè)版本已經(jīng)有這個(gè)問(wèn)題了,并且跑了一段時(shí)間,并沒(méi)有引起太大的問(wèn)題。那么在綜合考慮后,也許你可以不用緊急的修復(fù)這個(gè)問(wèn)題,而是可以繼續(xù)發(fā)布,在下一個(gè)
Sprint對(duì)問(wèn)題進(jìn)行查找,進(jìn)入第三步。如果上一個(gè)版本沒(méi)有這個(gè)問(wèn)題,那么可以集中考慮這個(gè)
Sprint編寫(xiě)的代碼的問(wèn)題,走進(jìn)第二步
代碼量不大,那么可以和同事一起進(jìn)行所有的代碼Review,如果還找不出來(lái),進(jìn)入
第三步代碼量比較大,那么這個(gè)時(shí)候除了和熟悉這部分代碼的同事一起Review代碼,還可以根據(jù)內(nèi)存泄露的速率和這次新增的業(yè)務(wù)邏輯,找到可疑的點(diǎn)。如果還是找不到,那么進(jìn)入
第三步。
<<微軟Debug CRT庫(kù)是如何追蹤C(jī)++內(nèi)存泄露的?>>: 這種做法只適合于小型的項(xiàng)目,而且對(duì)于第三方庫(kù)的內(nèi)存泄露無(wú)法進(jìn)行檢測(cè)。本文旨在通過(guò)分析微軟Debug CRT庫(kù)的實(shí)現(xiàn)的檢測(cè)內(nèi)存泄露的方式,從而闡述自我實(shí)現(xiàn)簡(jiǎn)易C++內(nèi)存泄露檢測(cè)的思想。
<<Windows程序內(nèi)存泄漏(Memory Leak)分析之UMDH>>: 這種方法有一定的局限:當(dāng)程序復(fù)雜,內(nèi)存頻繁的申請(qǐng)釋放,通過(guò)UMDH對(duì)比的文件將會(huì)非常的大,并且很難直接看出內(nèi)存泄露所在; 另外UMDH在收集信息的需要符號(hào)文件,不太適合于在客戶的機(jī)器上進(jìn)行操作。
<<Windows程序內(nèi)存泄漏(Memory Leak)分析之Windbg>>: 這種方法,需要分析者對(duì)Windbg和Windows的堆要比較熟悉,分析過(guò)程也相對(duì)比較麻煩,不是首選方法。
<<vmmap分析內(nèi)存泄露問(wèn)題>>: 雖然也可以用來(lái)做內(nèi)存泄露分析,但是一般本人喜歡用于做輔助分析,可以比較清晰的看出各種類型內(nèi)存的動(dòng)態(tài)變化。
<<Windows內(nèi)存泄露分析之DebugDialog>>: 這種是我目前分析內(nèi)存泄露問(wèn)題的首選方法,也是本案例中使用的主要方法, 其主要兩個(gè)步驟: 收集dump和自動(dòng)分析,從而找出可疑的內(nèi)存泄露對(duì)應(yīng)的函數(shù)調(diào)用棧。讀者可以跳轉(zhuǎn)到文章,查看詳細(xì)的信息,本文將精簡(jiǎn)原文所做的步驟和講解。
第二步 選擇你需要產(chǎn)生Dump的時(shí)間,最少要配置15分鐘,這個(gè)可以根據(jù)你項(xiàng)目產(chǎn)生Memory Leak的速度來(lái)決定。
內(nèi)存泄露的原因
class MemoryLeakClass{public:MemoryLeakClass(){m_pObj = new XXX_ResourceClass;}void DoSomething(){m_pObj->DoSomething();}~MemoryLeakClass(){;}private:XXX_ResourceClass* m_pObj;};





