国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
內(nèi)存泄漏的檢測、定位和解決經(jīng)驗總結(jié)
http://blog.csdn.net/freedomsky120/archive/2007/12/24/1965103.aspx

溫輝敏(wenhm@sina.com)
200605
【摘要】
結(jié)合局端MCU項目中CSS、NMS模塊內(nèi)存泄漏檢測、修正的過程,簡要介紹了內(nèi)存泄漏檢測的工具,提出了內(nèi)存泄漏檢測的一些方法(怎樣對程序結(jié)構(gòu)進行改造,怎樣對程序進行隔離以易于進行內(nèi)存泄漏檢測)。總結(jié)了內(nèi)存泄漏檢測過程中成功和失敗的體會,希望能對后來者有所啟發(fā)。
【關(guān)鍵詞】
內(nèi)存泄漏
一、故障或失誤概況
局端MCU項目CSS(Conference Schedule System)、NMSNetWork Management System)模塊自2.03版本起就有內(nèi)存泄露的問題,開發(fā) NGN版本時也花過大量的精力來爭取解決這個問題,雖然也修正了一些內(nèi)存泄漏,但最終檢測工具表面現(xiàn)象顯示剩下的內(nèi)存泄露都是所使用的開發(fā)庫的代碼產(chǎn)生的,于是也就大意的認為是所使用的ACE/TAO庫本身有內(nèi)存泄漏,于是無果而終,使這兩個模塊的內(nèi)存泄漏問題一直延續(xù)到2.03.20x版本。
由于后續(xù)測試部和開發(fā)部進行測試時引入了Robot來進行自動測試,使業(yè)務(wù)操作量巨升,此時CSS模塊的內(nèi)存泄漏問題就更明顯了,從程序啟動時的13M內(nèi)存,經(jīng)過一兩個月后可以飆升到200 M左右,正因為此局端MCU項目好幾個程序都采用了看門狗的方式來定時檢測程序的狀態(tài)防止程序當?shù)簟?/span>
由于問題比較嚴重,于是再次進行內(nèi)存泄漏問題的攻關(guān),測試時NMS模塊業(yè)務(wù)操作量小內(nèi)存泄漏不明顯,于是此次攻關(guān)重點是查CSS的內(nèi)存泄漏問題。
此次再次進行CSS行內(nèi)存泄露問題的研究,力爭解決CSS的內(nèi)存泄露問題,實在找不到解決方案(例如為所使用的開發(fā)庫的原因)也定位出具體原因供項目組參考。
二、診斷過程
2.1工具介紹
目前Windows平臺上流行的內(nèi)存泄露檢測工具有Rational PurifyBoundsChecker、insure++,由于CSS較復(fù)雜又是多線程采用Rational Purify工具程序就啟動不起來,無法進行檢測;parasoft 公司的insure++工具傳說中比較好用,但由于我們公司沒有相應(yīng)的licence無法使用;最后選擇采用限制版的BoundsChecker來進行檢測。
還有就是要一個好的實時檢測程序使用內(nèi)存狀況并能實時記錄下每個時刻內(nèi)存使用情況的工具,我們這里使用的是本部傳輸產(chǎn)品測試部自己開發(fā)的一個小工具MemSample。(見附錄1)
對于工具方面這也是個問題,若每個公司都有個統(tǒng)一可用工具列表,然后附上相應(yīng)的使用說明就可以省了許多精力和時間。現(xiàn)在好多工具都是自己去浩如煙海的網(wǎng)上找,有些還需要licence等,這是個很大的精力浪費。
2.2診斷概況
CSS模塊為后臺服務(wù)程序通過訪問Web頁面的形式來對外提供服務(wù),運行了該模塊的程序過一段時間后機器性能明顯下降,經(jīng)檢測為內(nèi)存嚴重消耗。測試部使用內(nèi)存監(jiān)視工具MemSample對各模塊的內(nèi)存進行監(jiān)測,發(fā)現(xiàn)在一個月內(nèi)CSS程序占用的內(nèi)存從初始的13M飆升到200M。
由現(xiàn)象可以判斷肯定是存在內(nèi)存泄漏問題,由于CSS對外提供服務(wù)接口繁多一時不知道那個接口導(dǎo)致的內(nèi)存泄漏,因此確定如下測試過程:
測試方法1:通過單元測試的方法來調(diào)用部分接口進行測試。
l         采用CPPUNIT測試框架輔助以樁程序的方式來模擬Web頁面手工操作的方式來調(diào)用相應(yīng)接口進行測試。
l         程序測試過程中采用內(nèi)存泄漏代碼級檢測工具BoundsChecker全程跟蹤程序中內(nèi)存分配和釋放情況。
l         采用內(nèi)存監(jiān)測工具MemSample對程序占用的整體內(nèi)存進行監(jiān)測并采集各時間段內(nèi)存占用數(shù)據(jù)。
經(jīng)過第一種測試方法發(fā)現(xiàn)了程序中存在的一些內(nèi)存泄漏,并解決之,但解決之后發(fā)現(xiàn)還是存在內(nèi)存泄漏,通過分析發(fā)現(xiàn)模擬測試步驟和真實環(huán)境下的操作唯一的不同點就是:
模擬測試是在程序內(nèi)部直接調(diào)用接口,而真實環(huán)境下是通過訪問Web頁面,Web頁面再通過CORBA協(xié)議來調(diào)用程序接口。即模擬測試少了CORBA調(diào)用那部分的操作,為此重新制定第二種測試方法:
測試方法2:真實操作環(huán)境下進行測試
l         由于接口繁多,重點挑一兩個使用頻繁的接口進行測試。
l         人工訪問調(diào)用所測接口的那個Web頁面,不斷頻繁刷新,保證和真實操作環(huán)境完全一致。
l         測試過程中啟動內(nèi)存監(jiān)測工具MemSampleCSS占用內(nèi)存進行監(jiān)測并采集各時間段內(nèi)存占用數(shù)據(jù)。
測試后發(fā)現(xiàn)所測接口均存在內(nèi)存泄漏,每次接口調(diào)用都會有幾十K的內(nèi)存泄漏,此時擴展到其它接口發(fā)現(xiàn)所有使用CORBA協(xié)議通過Web頁面調(diào)用的接口均存在內(nèi)存泄漏。比較兩種測試方法可以初步確定是在調(diào)用CORBA協(xié)議部分的代碼出現(xiàn)了內(nèi)存泄漏,下面進行整個檢測過程詳細描述。
2.3診斷過程
采用BoundsChecker檢測和Rational Purify工具不一樣,Rational Purify可以在程序運行中隨時給出即時的內(nèi)存泄漏報告,而使用BoundsChecker則只有在程序自行結(jié)束后才會觸發(fā)它去收集數(shù)據(jù)給出內(nèi)存泄漏報告(注意:必須是程序自己運行完畢退出,而不能人為的去關(guān)閉該程序否則得不到內(nèi)存泄漏報告)
2.3.1對程序的改造
由于要讓程序自動結(jié)束,所以要對程序結(jié)構(gòu)進行改造,前段時間部門推行的單元測試為此次內(nèi)存泄漏檢測提供了很好的基礎(chǔ)。
CSS模塊為單元測試專門創(chuàng)建了一個新的VC Project,共用CSS中的所有代碼,但自己工程中的單元測試代碼又不會影響CSS原來的代碼。此次進行內(nèi)存泄漏的檢測就首先打算運行單元測試的代碼然后檢測是否有內(nèi)存泄漏。
單元測試程序改造如下:
1)程序啟動時開啟兩個線程,一個CSS線程負責正常啟動CSS,另一個測試線程負責運行測試用例對已經(jīng)正常啟動的CSS進行測試。
2)測試線程運行測試用例完畢后要讓CSS線程退出,并結(jié)束自己,只有這樣BoundsChecker才能拿到內(nèi)存泄漏數(shù)據(jù)。
2.3.2內(nèi)存泄漏檢測
第一次內(nèi)存泄漏檢測,CSS測試程序運行一遍測試用例正常退出后,得到BoundsChecker的檢測報告顯示:
l         所有采取單態(tài)模式的類中的相應(yīng)的指針指向的動態(tài)分配的對象都沒有被釋放。
l         線程被異常終止時,該線程中動態(tài)分配的內(nèi)存沒有釋放掉。
l         動態(tài)分配的全局變量(對象)沒有被釋放掉。
l         絕大部分的內(nèi)存泄漏集中在ACE/TAO(ACECORBA)提供的一些函數(shù)里。
其中前三種情況就是1.問題描述中提到的在第一次內(nèi)存泄漏檢測就解決的,最后一個是造成內(nèi)存泄漏問題嚴重的罪魁禍首,在第二次內(nèi)存泄漏檢測才徹底解決,這里列下相應(yīng)的解決方法和思路。
2.3.3內(nèi)存泄漏修正方法
BoundsChecker Data Collection設(shè)置中將跟蹤的call stack深度加大即可以晰的看到每個內(nèi)存泄漏是從哪個函數(shù)哪條語句產(chǎn)生的。BoundsChecker出的報告中內(nèi)存泄漏數(shù)據(jù)和資源泄漏數(shù)據(jù)對于查找內(nèi)存泄漏問題都是非常有幫助的。[見附錄2、3]
根據(jù)報告進行內(nèi)存泄漏定位發(fā)現(xiàn)泄漏分為兩種:
1)在程序關(guān)閉時候的內(nèi)存泄漏,只有程序關(guān)閉時才發(fā)生的內(nèi)存泄漏,如一些動態(tài)分配的全局對象,線程沒有正常退出而是直接被Terminate掉等。
2)程序運行中的內(nèi)存泄漏,即運行中會不斷發(fā)生泄漏,如一段代碼動態(tài)分配了內(nèi)存忘釋放了,這樣這段代碼每次運行都會產(chǎn)生內(nèi)存泄漏。
 
2.3.3.1程序關(guān)閉時內(nèi)存泄漏檢測和修正方法
雖然程序關(guān)閉時才發(fā)生的內(nèi)存泄漏不會導(dǎo)致程序運行中內(nèi)存使用的增長,但由于BoundsChecker給出的報告中只給出程序運行期間發(fā)生的所有內(nèi)存泄漏,所有關(guān)閉時內(nèi)存泄漏和運行時內(nèi)存泄漏都混雜在一起不好定位,為此首先要解決關(guān)閉時的內(nèi)存泄漏問題,由于關(guān)閉時內(nèi)存泄漏一般都是動態(tài)分配的全局變量沒釋放、線程不是正常退出等情況產(chǎn)生的所以比較好定位。解決方法如下:
1)所有動態(tài)分配的全局變量在程序退出時都Delete掉。
2)讓所有線程都正常運行結(jié)束退出,而不是被異常Terminate掉。
3)所有使用單態(tài)模式的類都必須有專門的內(nèi)存清理函數(shù)在程序結(jié)束前調(diào)用。
經(jīng)過以上方法的處理后,CSS程序剩下的內(nèi)存泄漏全部集中在ACE/TAO(ACECORBA)提供的dll上。
2.3.3.2程序運行時內(nèi)存泄漏檢測和修正方法
第二次內(nèi)存泄漏檢測運行CSS測試程序得到的檢測報告發(fā)現(xiàn)的內(nèi)存泄露全部集中在ACE/TAO(ACECORBA)提供的dll上,原因可能有如下兩種:
1) 程序中使用ACETAO的函數(shù)不當沒有正確釋放內(nèi)存。
2) ACETAO庫確實是存在內(nèi)存泄露問題。
由于此時顯示內(nèi)存泄漏都是在TAO的函數(shù)中發(fā)生的,一下子沒了思路不知道怎么查了,只好一步一步的去查程序代碼了。
一開始測試程序只是將所有測試用例執(zhí)行一遍然后就退出,為了測試是否會有運行時內(nèi)存泄漏,讓測試程序?qū)⑺袦y試用例運行多遍才退出,理論上若有運行時內(nèi)存泄漏的話,運行n遍測試用例產(chǎn)生的內(nèi)存泄漏應(yīng)該是運行一遍產(chǎn)生的內(nèi)存泄漏的n倍。照著這個思路往下走,發(fā)現(xiàn)實際上并不是這么回事,基本上內(nèi)存泄漏的字節(jié)數(shù)不變,由此可見測試用例沒有覆蓋到真正產(chǎn)生運行時內(nèi)存泄漏的代碼,目前報告中發(fā)現(xiàn)的內(nèi)存泄漏都只是程序關(guān)閉時產(chǎn)生的內(nèi)存泄漏。
怎樣定位哪段代碼會產(chǎn)生運行時內(nèi)存泄漏呢?程序運行時內(nèi)存泄漏問題比較難定位,特別是程序有多個線程時,CSS內(nèi)存泄漏檢測首先采用的方法為進行線程隔離。
1)      線程隔離法
將程序中主要的可能產(chǎn)生內(nèi)存泄漏的線程一個個進行隔離,每次只運行其中的一個或關(guān)閉其中的一個,然后看BoundsChekcer產(chǎn)生的內(nèi)存泄漏字節(jié)數(shù)是否有變化,以此來判斷該線程是否會產(chǎn)生內(nèi)存泄漏。若該線程會產(chǎn)生內(nèi)存泄漏則對該線程的代碼進行仔細分析以找出原因。
CSS程序進行線程隔離后也發(fā)現(xiàn)這些線程都不產(chǎn)生內(nèi)存泄漏。
2)      功能檢查法
此時只好從CSS的功能上來定位了,CSS主要是和Web進行交互,接受Web發(fā)過來的指令然后進行開關(guān)會等操作。分析由于測試程序只是測試CSS的內(nèi)部流程,而沒有涉及到WebCSS的接口那塊,而WebCSS之間是使用CORBA機制通訊的,恰好內(nèi)存泄漏報告也顯示內(nèi)存泄漏基本集中在TAO(CORBA開發(fā)庫)那部分。
于是選擇一個Web頁面(獲取mcu列表),不斷的刷新該頁面,發(fā)現(xiàn)此時CSS使用內(nèi)存果然在不斷上漲。也就是所獲取mcu列表這個功能對應(yīng)的代碼會產(chǎn)生內(nèi)存泄漏。
由于這個小功能對應(yīng)的代碼是有限的就幾十行,仔細的檢查也沒發(fā)現(xiàn)什么問題,此時想到測試部認為NMS模塊沒有內(nèi)存泄漏,只要對比NMS模塊的類似功能的代碼就能知道內(nèi)存泄漏的原因了。但檢查發(fā)現(xiàn)兩邊代碼是一樣的,然后去測NMS的相關(guān)頁面發(fā)現(xiàn)NMS也有內(nèi)存泄漏,只是因為NMS業(yè)務(wù)量比較小不太容易暴露該問題而已。
此時更相信可能是TAO開發(fā)庫自己產(chǎn)生的內(nèi)存泄漏了,正要放棄之際,慕然出現(xiàn)了轉(zhuǎn)機,我們科室的李喜欣也使用了TAO庫,此時彭峰和他也參與進內(nèi)存泄漏的攻關(guān),經(jīng)檢測發(fā)現(xiàn)喜欣的程序沒有內(nèi)存泄漏。
一開始認為是使用的TAO庫的版本不一樣,于是就將我們的代碼放入李喜欣TAO庫所在環(huán)境中測試,發(fā)現(xiàn)在他哪里還是也有內(nèi)存泄漏,也就是所和TAO庫的版本沒有關(guān)系??赡艽_實是代碼中函數(shù)使用方法有誤。
于是針對那部分功能代碼開始一條條語句屏蔽以期找出產(chǎn)生內(nèi)存泄漏的語句,功夫不負有心人當我們將一條memset()語句屏蔽掉后終于沒有內(nèi)存泄漏了。
分析原因是由于memset將一個CORBA對象所占內(nèi)存清零了,雖然IDL中定義的為一個結(jié)構(gòu),但經(jīng)過IDL文件的編譯,實際上在CORBA已將IDL中的結(jié)構(gòu)轉(zhuǎn)換為相應(yīng)的CORBA對象了,該對象中含有智能指針,這些指針在對象創(chuàng)建時都已經(jīng)指向了一些動態(tài)分配的空間,由于memset操作,導(dǎo)致這些指針全部清零,于是那些指針原來指向動態(tài)分配的空間就永遠都得不到釋放進而產(chǎn)生了內(nèi)存泄漏。
修正memset問題后就徹底的解決了內(nèi)存泄漏問題。
三、推廣建議
本文簡要介紹了進行內(nèi)存泄漏檢測的一些工具,并提出了一些進行內(nèi)存泄漏檢測的有效方法和經(jīng)驗,對于要進行內(nèi)存泄漏檢測的項目具有一定的借鑒意義。
若需要文中提到的一些內(nèi)存檢測工具可以聯(lián)系作者。
四、后記
經(jīng)過漫長的內(nèi)存泄漏檢測終于將內(nèi)存泄漏問題解決了,修正CSSNMS的內(nèi)存一直都穩(wěn)定在13M左右,在查找內(nèi)存泄漏的問題中有以下幾點體會:
1.       不要隨便懷疑別人首先要懷疑自己,第一次內(nèi)存泄漏檢測沒有徹底找出原因就是因為認為是開發(fā)庫自己的內(nèi)存泄漏,第二次也差點就打算收工了。最后發(fā)現(xiàn)還是自己使用不當導(dǎo)致的。
2.       要有耐心,不能煩躁,當一個問題你找不到一絲絲線索時多和別人交流是很有幫助的,這次能徹底解決內(nèi)存泄漏就是由于彭峰和李喜欣的加入,三個丑皮匠頂個諸葛亮真是至理名言。
3.       工具很重要,使用好的工具能事半功倍。
 

附錄1.監(jiān)視程序內(nèi)存使用的工具: MemSample
 
 
附錄2:BoundsChecker內(nèi)存泄漏數(shù)據(jù)截圖
 
 

附錄3:BoundsChecker資源泄漏數(shù)據(jù)截圖
 


(#)

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
C 內(nèi)存泄露及處理方法
淺談C/C++內(nèi)存泄漏及其檢測工具
什么是內(nèi)存泄漏?怎么產(chǎn)生的?如何檢測?
C語言運行時庫詳解
檢測內(nèi)存泄露的原理
C/C++語言內(nèi)存分析工具
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服