陳 楠
(中國(guó)石油化工股份有限公司 石油物探技術(shù)研究院, 南京 211103)
基于C++的動(dòng)態(tài)內(nèi)存實(shí)時(shí)監(jiān)測(cè)器①
陳 楠
(中國(guó)石油化工股份有限公司 石油物探技術(shù)研究院, 南京 211103)
通過(guò)對(duì)地球物理軟件研發(fā)過(guò)程中比較常見(jiàn)內(nèi)存錯(cuò)誤的調(diào)研與總結(jié), 設(shè)計(jì)并實(shí)現(xiàn)了一個(gè)基于C/C++的動(dòng)態(tài)內(nèi)存檢測(cè)工具, 采用內(nèi)嵌與關(guān)鍵函數(shù)截獲方式, 對(duì)編譯器開(kāi)放接口進(jìn)行擴(kuò)展與改進(jìn). 該工具通過(guò)對(duì)軟件運(yùn)行過(guò)程中堆內(nèi)存使用情況的實(shí)時(shí)收集、分類統(tǒng)計(jì)與分析, 達(dá)到動(dòng)態(tài)的監(jiān)控與檢測(cè)內(nèi)存堆棧錯(cuò)誤的目的. 以中國(guó)石化石油物探技術(shù)研究院自主研發(fā)的油氣綜合解釋系統(tǒng)NEWS子系統(tǒng)-疊前疊后聯(lián)合解釋模塊主要流程為例, 用該檢測(cè)工具對(duì)其進(jìn)行全面的測(cè)試與應(yīng)用. 實(shí)踐表明, 嵌入監(jiān)測(cè)器的應(yīng)用軟件在開(kāi)發(fā)過(guò)程中大幅降低了內(nèi)存泄漏現(xiàn)象, 運(yùn)行時(shí)減少了內(nèi)存錯(cuò)誤導(dǎo)致的異常崩潰現(xiàn)象, 提高了應(yīng)用軟件的穩(wěn)定性, 并能夠?qū)﹂_(kāi)發(fā)以及測(cè)試人員快速定位與分析軟件錯(cuò)誤起到較強(qiáng)的指導(dǎo)作用.
內(nèi)存泄漏; 重載; 檢測(cè); 調(diào)用棧; NEWS
隨著野外油氣勘探技術(shù)的發(fā)展與進(jìn)步, 采集數(shù)據(jù)信息量的增多也使得地震數(shù)據(jù)變得日趨龐大, 大數(shù)據(jù)量任務(wù)處理一直是地球物理軟件研發(fā)人員不斷研究與探索的技術(shù)課題, 計(jì)算機(jī)物理內(nèi)存的管理也越來(lái)越復(fù)雜[1], 操作系統(tǒng)從32位升級(jí)到64位, 理論上將64位CPU的尋址空間從4GB擴(kuò)展到了無(wú)窮大(遠(yuǎn)遠(yuǎn)超出物理內(nèi)存大小), 解決了程序設(shè)計(jì)中物理內(nèi)存分配的上限問(wèn)題, 不過(guò)這樣往往導(dǎo)致了另外一個(gè)問(wèn)題: 程序員們對(duì)手動(dòng)釋放物理內(nèi)存的意識(shí)逐漸變得淡薄, 以至于在系統(tǒng)性能變得低下甚至頻臨崩潰時(shí)才意識(shí)到問(wèn)題嚴(yán)重,但此時(shí)的開(kāi)發(fā)規(guī)模也使得排查工作變得復(fù)雜無(wú)序, 筆者雖具備多年一線軟件研發(fā)經(jīng)驗(yàn), 但當(dāng)出現(xiàn)內(nèi)存問(wèn)題累積引發(fā)的系統(tǒng)性能問(wèn)題方面, 也感到維護(hù)工作非常困難, 輕者按程序流程分支逐一排查測(cè)試, 重則推倒重來(lái), 新手遇到類似問(wèn)題更是感到無(wú)從下手, 往往嚴(yán)重影響項(xiàng)目研發(fā)進(jìn)度. 針對(duì)這些現(xiàn)象, 第三方解決方案其實(shí)已經(jīng)存在, Windows系統(tǒng)下有MFC內(nèi)嵌的內(nèi)存監(jiān)測(cè)工具可以實(shí)時(shí)跟蹤應(yīng)用軟件內(nèi)存情況并提示定位內(nèi)存泄漏信息[2,3], 但該工具不支持MingW編譯器, Linux系統(tǒng)下相對(duì)來(lái)說(shuō)就沒(méi)有那么容易使用的解決方案, 而mpatrol之類的現(xiàn)有工具, 在易用性、附加開(kāi)銷和性能等方面都不是很理想[4-6].
一個(gè)成熟的軟件產(chǎn)品往往都已經(jīng)對(duì)外發(fā)布試用與銷售, 隨著應(yīng)用范圍的擴(kuò)大, 不可避免地也會(huì)存在一定數(shù)量的bug, 如果不具備遠(yuǎn)程調(diào)試的條件, 開(kāi)發(fā)人員僅僅從用戶的反饋信息中很難準(zhǔn)確定位軟件在使用過(guò)程中出現(xiàn)的問(wèn)題.
綜上所述, 在軟件工程開(kāi)發(fā)的過(guò)程中, 一個(gè)具備全程動(dòng)態(tài)跟蹤功能的、跨平臺(tái)的錯(cuò)誤定位與內(nèi)存檢測(cè)工具是很有必要的.
一般情況下, 實(shí)時(shí)檢測(cè)程序應(yīng)該具備以下幾個(gè)基本功能: ①全程跟蹤并記錄程序中內(nèi)存分配和釋放情況[7]; ②監(jiān)控分配的內(nèi)存是否為有效數(shù)據(jù); ③在發(fā)生異常崩潰時(shí)進(jìn)行跳轉(zhuǎn)處理并回溯崩潰點(diǎn)的函數(shù)調(diào)用棧, 提示開(kāi)發(fā)人員定位崩潰點(diǎn)位置找出錯(cuò)誤; ④支持線程安全.
3.1 程序調(diào)用棧(call stack)原理分析
功能: 主要用于程序異常退出時(shí)尋找錯(cuò)誤點(diǎn), 回溯堆棧, 列出當(dāng)前錯(cuò)誤序列函數(shù)的調(diào)用關(guān)系.
原理: 通過(guò)對(duì)當(dāng)前堆棧的分析, 找到其上層函數(shù)在棧中的幀地址, 再分析上層函數(shù)的堆棧, 再找再上層的幀地址, 一直找到最頂層為止, 幀地址指的是一塊在棧上存放局部變量, 上層返回地址, 及寄存器值的空間.
要了解調(diào)用棧, 首先需要了解函數(shù)的調(diào)用過(guò)程,下面用一段簡(jiǎn)單代碼作為例子:
通過(guò)對(duì)代碼的反匯編可以看到(圖1), 進(jìn)入add函數(shù)后, 首先進(jìn)行的操作是將當(dāng)前的棧基址ebp壓棧(此?;肥钦{(diào)用者main函數(shù)的), 然后將ebp指向棧頂esp, 接下來(lái)再進(jìn)行函數(shù)內(nèi)的處理流程. 函數(shù)結(jié)束前,會(huì)將函數(shù)調(diào)用者的?;坊謴?fù), 然后返回準(zhǔn)備執(zhí)行下一指令. 這個(gè)過(guò)程中, 棧上的空間展布如圖2 所示.
圖1 反匯編代碼解析
可以發(fā)現(xiàn), 每調(diào)用一次函數(shù), 都會(huì)對(duì)調(diào)用者的?;?ebp)進(jìn)行壓棧操作(圖2), 并且由于?;肥怯僧?dāng)時(shí)棧頂指針(esp)而來(lái), 會(huì)發(fā)現(xiàn), 各層函數(shù)的棧基址很巧妙的構(gòu)成了一個(gè)鏈, 即當(dāng)前的?;分赶蛳乱粚雍瘮?shù)?;匪诘奈恢? 如圖2所示.
圖2 調(diào)用棧關(guān)系
了解函數(shù)的調(diào)用過(guò)程, 想要回溯調(diào)用棧也就容易了, 首先獲取當(dāng)前函數(shù)的?;?寄存器ebp)的值, 然后獲取該地址所指向的棧的值, 該值也就是下層函數(shù)的棧基址, 找到下層函數(shù)的?;泛? 重復(fù)剛才的動(dòng)作, 即可以將每一層函數(shù)的棧基址都找出來(lái), 這也就是我們所需要的調(diào)用棧了,前面描述的是函數(shù)棧的內(nèi)存結(jié)構(gòu)關(guān)系和調(diào)用邏輯, 在不同編譯器條件下可能會(huì)出現(xiàn)內(nèi)存高低位置的互換, 但并不影響對(duì)棧結(jié)構(gòu)的分析和研究[8,9].
3.2 動(dòng)態(tài)內(nèi)存泄漏檢測(cè)
功能: 實(shí)時(shí)監(jiān)控內(nèi)存分配與釋放情況.
原理: 重載與替換系統(tǒng)內(nèi)存分配釋放函數(shù).
棧內(nèi)存在函數(shù)結(jié)束時(shí)由系統(tǒng)自動(dòng)回收釋放, 所以不會(huì)造成泄漏現(xiàn)象, 一般我們常說(shuō)的內(nèi)存泄漏是指堆內(nèi)存的分配與釋放不匹配導(dǎo)致[10-12]. 堆內(nèi)存是程序從堆中分配的, 大小任意的(理論上內(nèi)存塊的大小可以在程序運(yùn)行期決定), 使用完后必須顯示釋放的內(nèi)存. 應(yīng)用程序一般使用malloc, realloc, new等函數(shù)從堆中分配到一塊內(nèi)存, 使用后, C++程序員必須手動(dòng)調(diào)用相應(yīng)的free或delete釋放該內(nèi)存塊, 否則, 這塊內(nèi)存就不能被系統(tǒng)回收再次使用, 從而造成泄漏. 內(nèi)存泄漏不僅僅包含堆內(nèi)存的泄漏, 還可以包含系統(tǒng)資源的泄漏(resource leak), 比如核心態(tài)指針如HANDLE, GDI Object, SOCKET, Interface等, 從根本上說(shuō)這些由操作系統(tǒng)分配的對(duì)象也消耗內(nèi)存, 如果這些對(duì)象發(fā)生泄漏最終也會(huì)導(dǎo)致物理內(nèi)存的丟失. 而且, 某些對(duì)象消耗的是核心態(tài)內(nèi)存, 這些對(duì)象嚴(yán)重泄漏時(shí)會(huì)導(dǎo)致整個(gè)操作系統(tǒng)不穩(wěn)定. 所以相比之下, 系統(tǒng)資源的泄漏比堆內(nèi)存的泄漏更為嚴(yán)重[13]. 以發(fā)生的方式來(lái)分類, 內(nèi)存泄漏可以分為4類:
① 常發(fā)性內(nèi)存泄漏. 發(fā)生內(nèi)存泄漏的代碼會(huì)被多次執(zhí)行到, 每次被執(zhí)行的時(shí)候都會(huì)導(dǎo)致一塊內(nèi)存泄漏, 這種泄漏在地球物理軟件批量處理模塊中比較常見(jiàn).
② 偶發(fā)性內(nèi)存泄漏. 發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過(guò)程下才會(huì)發(fā)生, 比如在某分支條件下的用戶交互操作. 對(duì)于特定的環(huán)境, 偶發(fā)性的也許就變成了常發(fā)性的. 所以測(cè)試環(huán)境和測(cè)試方法對(duì)檢測(cè)內(nèi)存泄漏也是至關(guān)重要.
③ 一次性內(nèi)存泄漏. 發(fā)生內(nèi)存泄漏的代碼只會(huì)被執(zhí)行一次, 或者由于算法上的缺陷, 導(dǎo)致總會(huì)有一塊僅且一塊內(nèi)存發(fā)生泄漏. 比如, 在類的構(gòu)造函數(shù)中分配內(nèi)存, 在析構(gòu)函數(shù)中卻沒(méi)有釋放該內(nèi)存, 所以內(nèi)存泄漏只會(huì)發(fā)生一次, 或者是一些全局靜態(tài)指針等等.
④ 隱式內(nèi)存泄漏. 程序在運(yùn)行過(guò)程中不停的分配內(nèi)存, 但是直到結(jié)束的時(shí)候才釋放內(nèi)存. 嚴(yán)格的說(shuō)這里并沒(méi)有發(fā)生內(nèi)存泄漏, 因?yàn)樽罱K程序釋放了所有申請(qǐng)的內(nèi)存. 但是對(duì)于一個(gè)服務(wù)器程序, 需要運(yùn)行幾天, 幾周甚至幾個(gè)月, 不及時(shí)釋放內(nèi)存也可能導(dǎo)致最終耗盡系統(tǒng)的所有內(nèi)存. 所以, 我們稱這類內(nèi)存泄漏為隱式內(nèi)存泄漏, 作為一般的用戶, 通常感覺(jué)不到內(nèi)存泄漏的存在. 真正有危害的是內(nèi)存泄漏的堆積[14],這會(huì)最終消耗盡系統(tǒng)所有的內(nèi)存. 從這個(gè)角度來(lái)說(shuō),一次性內(nèi)存泄漏并沒(méi)有什么危害, 因?yàn)樗粫?huì)堆積,而隱式內(nèi)存泄漏危害性則較大, 因?yàn)樗y被檢測(cè)到,所以這方面的問(wèn)題需要從軟件程序的優(yōu)化方面考慮解決.
檢測(cè)內(nèi)存泄漏的關(guān)鍵是要能截獲住對(duì)分配內(nèi)存和釋放內(nèi)存的函數(shù)的調(diào)用[15]. 截獲住這兩個(gè)函數(shù), 我們就能跟蹤每一塊內(nèi)存的生命周期, 比如, 每當(dāng)成功的分配一塊內(nèi)存后, 就把它的指針加入一個(gè)全局的list中; 每當(dāng)釋放一塊內(nèi)存, 再把它的指針從list中刪除.這樣, 當(dāng)程序結(jié)束的時(shí)候, list中剩余的指針就是指向那些沒(méi)有被釋放的內(nèi)存. 這里只是簡(jiǎn)單的描述了檢測(cè)內(nèi)存泄漏的基本原理[16], 文章后面再詳述討論. 在new/delete操作中, C++為開(kāi)發(fā)人員產(chǎn)生了對(duì)operator new和operator delete的調(diào)用. 這是不能改變的. 對(duì)于"new int", 編譯器會(huì)產(chǎn)生一個(gè)調(diào)用"operator new(sizeof(int))", 而對(duì)于"new char[10]", 編譯器會(huì)產(chǎn)生"operator new[](sizeof(char) * 10)"(如果new后面跟的是一個(gè)類名的話, 編譯器還要調(diào)用該類的構(gòu)造函數(shù)).類似地, 對(duì)于"delete ptr"和"delete[] ptr", 編譯器會(huì)產(chǎn)生"operator delete(ptr)"調(diào)用和"operator delete[](ptr)"調(diào)用(如果ptr的類型是指向?qū)ο蟮闹羔樀脑? 那在operator delete之前還要調(diào)用對(duì)象的析構(gòu)函數(shù)). 當(dāng)用戶沒(méi)有提供這些操作符時(shí), 編譯系統(tǒng)自動(dòng)提供其定義;而當(dāng)用戶自己提供了這些操作符時(shí), 就覆蓋了編譯器提供的函數(shù)版本, 從而找到了可獲得對(duì)動(dòng)態(tài)內(nèi)存分配操作的精確跟蹤和控制的入口. 基于此, 利用自定義宏在用戶程序中進(jìn)行替換, 重載操作符operator new,格式如下所示.
void* operator new(size_t nsize, const char* cfile,
其他內(nèi)存分配操作符如表1所示, 重載后的operator new可以跟蹤覆蓋應(yīng)用程序內(nèi)部所有的內(nèi)存分配調(diào)用, 并在指定的檢查點(diǎn)上對(duì)不匹配的new和delete操作進(jìn)行自定義處理.
表1 其他內(nèi)存分配操作符
3.3 功能擴(kuò)展
3.3.1 監(jiān)測(cè)記錄
通過(guò)重載系統(tǒng)內(nèi)存操作符,用戶接替了編譯器對(duì)物理內(nèi)存分配的管理,靈活度大幅提高, 此時(shí)可以嵌入必要的記錄機(jī)制[15,16], 達(dá)到用戶對(duì)應(yīng)用程序內(nèi)存使用情況的全面監(jiān)測(cè). 比較常用的方法是記錄分配內(nèi)存的指針地址[17-20], 這樣消耗的內(nèi)存空間比較小, 檢索的速度也比較快, 為了提高檢索效率, 可以定義STL的散列表對(duì)象, 把申請(qǐng)內(nèi)存的文件名、行號(hào)、對(duì)象大小信息分別存入file、line和size字段中, 然后返回(malloc返回的指針 + sizeof(new_ptr_list_t)). 在delete時(shí), 則在散列表中搜索, 如果找到的話((char*)鏈表指針 + sizeof(new_ptr_list_t) == 待釋放的指針), 則調(diào)整鏈表、釋放內(nèi)存, 找不到的話報(bào)告刪除非法指針并abort, 過(guò)程如圖3所示. 要得到精確的內(nèi)存泄漏檢測(cè)報(bào)告, 可以在文件開(kāi)頭包含"debug_new.h". 包含的位置應(yīng)當(dāng)盡可能早, 除非跟系統(tǒng)的頭文件(典型情況是STL的頭文件)發(fā)生了沖突. 在某些情況下, 可能會(huì)不希望debug_new重定義new, 這時(shí)可以在包含debug_new.h之前定義DEBUG_NEW_NO_NEW_ REDEFINITION, 這樣的話, 在用戶應(yīng)用程序中應(yīng)使用debug_new來(lái)代替new(順便提一句, 沒(méi)有定義DEBUG_NEW_NO_NEW_REDEFINITION時(shí)也可以使用debug_new代替new). 在源文件中也許就該這樣寫(xiě):
并在需要追蹤內(nèi)存分配的時(shí)候全部使用debug_new(考慮使用全局替換). 用戶可以選擇定義DEBUG_NEW_EMULATE_MALLOC, 這樣debug_new.h會(huì)使用debug_new和delete來(lái)模擬malloc和free操作, 使得用戶程序中的malloc和free操作也可以被跟蹤, 反之也可以選擇性的宏定義啟動(dòng)開(kāi)關(guān),在發(fā)布版本中用戶可以關(guān)閉跟蹤功能, 避免實(shí)際應(yīng)用中效率的降低.
圖3 監(jiān)測(cè)記錄流程圖
3.3.2 多線程支持
線程是否可重入是編寫(xiě)監(jiān)測(cè)器API函數(shù)必須考慮的情況, 線程安全問(wèn)題都是由全局變量及靜態(tài)變量引起的, 內(nèi)存監(jiān)測(cè)器本身就是一個(gè)全局控制器[21-23], 內(nèi)部有比較頻繁的I/O操作, 所以要加入讀寫(xiě)互斥鎖用以保證線程安全性[24,25], 加入互斥鎖機(jī)制后的監(jiān)控器才能提供多線程支持, 這也是通用性設(shè)計(jì)的一個(gè)方面.
中石化物探院NEWS軟件子系統(tǒng)-“疊前疊后聯(lián)合解釋軟件”是一套集實(shí)時(shí)疊前分析、偏移距/入射角部分疊加、AVO屬性分析及P波疊前裂縫檢測(cè)等功能為一體的綜合性疊前數(shù)據(jù)解釋工具, 軟件工程方面也是具備了實(shí)時(shí)聯(lián)動(dòng)分析、交互圖形顯示和批量處理功能等綜合特征. 前期研發(fā)過(guò)程中較側(cè)重于模塊功能效果開(kāi)發(fā), 導(dǎo)致了該系統(tǒng)自1.0版本起就有輕微的內(nèi)存泄漏與越界現(xiàn)象, 但并不明顯, 不影響研究使用, 隨著功能的擴(kuò)充和應(yīng)用范圍的加大, 在經(jīng)過(guò)反復(fù)的交互使用與圖形顯示輸出后, 出現(xiàn)了內(nèi)存使用明顯增多的現(xiàn)象, 從程序啟動(dòng)時(shí)的80M, 經(jīng)過(guò)約168小時(shí)的方位各向異性批量處理運(yùn)算后可以飆升到800 M左右, 運(yùn)行該模塊的機(jī)器性能明顯下降.
由于工程代碼量大, 程序復(fù)雜, 用傳統(tǒng)的手工逐一排查方式工作量和風(fēng)險(xiǎn)性都很大, 開(kāi)發(fā)團(tuán)隊(duì)隨即在系統(tǒng)中嵌入了動(dòng)態(tài)內(nèi)存檢測(cè)工具, 進(jìn)行了全覆蓋的排查, 原因分析與修正: 1、交互過(guò)程中有零散的內(nèi)存泄漏現(xiàn)象, 通過(guò)檢測(cè)器記錄的泄漏位置逐一修正釋放. 2、檢測(cè)器記錄顯示, 在進(jìn)行單機(jī)多線程并行計(jì)算時(shí),程序定義的n個(gè)線程并發(fā)進(jìn)行內(nèi)存分配, 并將指針傳遞給一個(gè)數(shù)據(jù)存儲(chǔ)容器, 由m個(gè)線程從數(shù)據(jù)存儲(chǔ)進(jìn)行數(shù)據(jù)處理和內(nèi)存釋放. 由于 n 遠(yuǎn)大于m, 或者m個(gè)線程數(shù)據(jù)處理的時(shí)間過(guò)長(zhǎng), 導(dǎo)致內(nèi)存分配的速度遠(yuǎn)大于內(nèi)存被釋放的速度. 這種問(wèn)題在系統(tǒng)中較難發(fā)現(xiàn), 程序可能運(yùn)行一段時(shí)間沒(méi)有問(wèn)題, 從而通過(guò)了不嚴(yán)密的系統(tǒng)測(cè)試. 但是如果測(cè)網(wǎng)范圍大, 計(jì)算時(shí)間長(zhǎng)的情況下, 系統(tǒng)將不定時(shí)的崩潰, 而且崩潰的原因從程序表象上都比較難檢測(cè). 為了解決這種問(wèn)題, 我們?cè)跈z測(cè)器內(nèi)部增加了一個(gè)動(dòng)態(tài)檢測(cè)模塊, 同時(shí)啟動(dòng)一個(gè)分析線程, 每隔一定的時(shí)間間隔就計(jì)算一下當(dāng)前的以分配而尚未釋放的內(nèi)存信息, 并以內(nèi)存的分配位置為關(guān)鍵字進(jìn)行統(tǒng)計(jì), 查看在同一位置(相同文件名和行號(hào))所分配的內(nèi)存總量和其占進(jìn)程總內(nèi)存量的百分比. 這樣在程序運(yùn)行過(guò)程中, 用戶能夠?qū)Τ绦虻膭?dòng)態(tài)內(nèi)存分配狀況進(jìn)行監(jiān)視. 當(dāng)客戶監(jiān)視一個(gè)運(yùn)行中的進(jìn)程時(shí), 被監(jiān)視進(jìn)程的內(nèi)存子系統(tǒng)將把內(nèi)存分配和釋放的信息實(shí)時(shí)傳送給檢測(cè)器. 檢測(cè)器則每隔一定的時(shí)間間隔就對(duì)所接收到的信息進(jìn)行統(tǒng)計(jì), 計(jì)算該進(jìn)程總的內(nèi)存使用量, 同時(shí)以調(diào)用new或者malloc進(jìn)行內(nèi)存分配的文件名和行號(hào)為索引值, 計(jì)算每個(gè)內(nèi)存分配動(dòng)作所分配而未釋放的內(nèi)存總量. 用這種方法, 如果在連續(xù)多個(gè)時(shí)間間隔的統(tǒng)計(jì)結(jié)果中, 某文件的某行所分配的內(nèi)存總量不斷增長(zhǎng)而始終沒(méi)有到達(dá)一個(gè)平衡點(diǎn)甚至回落, 說(shuō)明該位置的內(nèi)存分配方式需要調(diào)整了. 當(dāng)?shù)玫給perator new 的信息時(shí), 記錄內(nèi)存分配信息, 當(dāng)收到operator delete 消息時(shí), 刪除相應(yīng)的內(nèi)存分配信息.
借助內(nèi)嵌的call stack調(diào)用?;厮輽C(jī)制, 測(cè)試過(guò)程中出現(xiàn)的程序異常崩潰, 可以快速準(zhǔn)確的定位到出錯(cuò)文件與行號(hào)(如圖4及圖5所示), 使得糾錯(cuò)效率大幅度的提高, 修正后的“疊前疊后聯(lián)合解釋軟件”在實(shí)際生產(chǎn)應(yīng)用中運(yùn)行穩(wěn)定, 計(jì)算速度也得到明顯提升.
圖4 異常函數(shù)示例
圖5 異常錯(cuò)誤定位
圖6 內(nèi)存泄漏監(jiān)控記錄
開(kāi)發(fā)了一套跨平臺(tái)的基于C/C++的動(dòng)態(tài)內(nèi)存檢測(cè)工具, 集成了函數(shù)調(diào)用?;厮?、實(shí)時(shí)內(nèi)存分配監(jiān)測(cè)、內(nèi)存使用與釋放回饋等技術(shù), 以圖形或者文本的方式向開(kāi)發(fā)用戶提交檢測(cè)預(yù)警記錄(如圖6所示), 在實(shí)際項(xiàng)目的使用中具備以下幾個(gè)特征:
① 大型軟件開(kāi)發(fā)過(guò)程明顯減少調(diào)試時(shí)間;
② 支持多平臺(tái)和跨平臺(tái)開(kāi)發(fā);
③ 降低維護(hù)和支持成本;
④ 實(shí)時(shí)排除算法錯(cuò)誤;
⑤ 減少軟件缺陷提高產(chǎn)品信譽(yù);
⑥ 能夠與項(xiàng)目產(chǎn)品的開(kāi)發(fā)生命周期無(wú)縫集成.
1 陳楠,祝媛媛,張光德,徐鈺.基于QT的地震勘探可擴(kuò)展平臺(tái)研發(fā)與應(yīng)用.華北地震科學(xué),2013,4:1003–1375.
2 周宇.基于調(diào)用棧完整性的緩沖區(qū)溢出檢測(cè)方法.計(jì)算機(jī)安全,2010,(3):16–19.
3 管曉宏,馮力,孫杰,等.Linux環(huán)境下基于調(diào)用棧圖的入侵檢測(cè)方法: CN,CN 1710866 A. 2005.
4 吳多多,楊偉偉,肖力濤.利用堆棧模擬C語(yǔ)言中函數(shù)的調(diào)用過(guò)程.科技信息,2011,(15).
5 楊禮波,張志亮.在堆棧緩沖區(qū)溢出中程序調(diào)用的分析和研究.電腦知識(shí)與技術(shù),2010,6(17):4686–4689.
6 徐建國(guó).網(wǎng)絡(luò)化制造系統(tǒng)中虛擬加工若干關(guān)鍵技術(shù)研究[博士學(xué)位論文].南京:南京理工大學(xué),2007.
7 肖謙,李中升,漆鋒濱.Linux下函數(shù)棧大小的自動(dòng)計(jì)算技術(shù).計(jì)算機(jī)工程,2011,(S1).
8 梁玉,傅建明,彭國(guó)軍,等.S-Tracker: 基于棧異常的 shellcode檢測(cè)方法.華中科技大學(xué)學(xué)報(bào)(自然科學(xué)版),2014,(11): 39–46.
9 楊東.ARM嵌入式系統(tǒng)異常調(diào)試的研究和實(shí)現(xiàn)[碩士學(xué)位論文].上海:上海交通大學(xué),2009.
10 戚曉芳,周曉宇,徐曉晶,等.一種組合式基于調(diào)用棧的程序切片方法.東南大學(xué)學(xué)報(bào)(自然科學(xué)版),2011,41(6):1171–1176.
11 周國(guó)亮,朱永利,王桂蘭,等.實(shí)時(shí)大數(shù)據(jù)處理技術(shù)在狀態(tài)監(jiān)測(cè)領(lǐng)域中的應(yīng)用.第六屆電工技術(shù)前沿問(wèn)題學(xué)術(shù)論壇. 2014.
12 王呈祥.基于共享內(nèi)存的通用OLE Process Control3.0服務(wù)器的研究與設(shè)計(jì)[碩士學(xué)位論文].長(zhǎng)春:吉林大學(xué),2013.
13 劉黎志,劉君.空氣質(zhì)量實(shí)時(shí)監(jiān)測(cè)系統(tǒng)的內(nèi)存泄漏.武漢工程大學(xué)學(xué)報(bào),2012,34(6):74–78.
14 周游弋.集群監(jiān)控系統(tǒng)中內(nèi)存數(shù)據(jù)庫(kù)的設(shè)計(jì)與應(yīng)用研究[碩士學(xué)位論文].上海:復(fù)旦大學(xué),2010.
15 張飛.實(shí)時(shí)嵌入式操作系統(tǒng)動(dòng)態(tài)內(nèi)存管理研究[學(xué)位論文].合肥:中國(guó)科學(xué)技術(shù)大學(xué),2008.
16 李明.多核路由器動(dòng)態(tài)內(nèi)存分配器的設(shè)計(jì)與實(shí)現(xiàn)[碩士學(xué)位論文].南京:南京理工大學(xué), 2011.
17 劉曉偉.基于Linux的電力系統(tǒng)實(shí)時(shí)監(jiān)測(cè)系統(tǒng)的開(kāi)發(fā)[碩士學(xué)位論文].武漢:華中科技大學(xué),2006.
18 何波玲,張志春.內(nèi)存信息自動(dòng)監(jiān)控器的設(shè)計(jì)與實(shí)現(xiàn).信息安全與技術(shù),2015,(6).
19 姚志強(qiáng).一個(gè)實(shí)用的自釋放內(nèi)存TSR程序的設(shè)計(jì)要素.福建師范大學(xué)學(xué)報(bào)(自然科學(xué)版),1997,(2):27–32.
20 吳民,涂奉生.Linux下面向函數(shù)的動(dòng)態(tài)內(nèi)存泄漏監(jiān)測(cè).計(jì)算機(jī)工程與應(yīng)用,2003,39(6):37–40.
21 孝瑞.內(nèi)存動(dòng)態(tài)安全監(jiān)測(cè)及防范研究[碩士學(xué)位論文].保定:華北電力大學(xué),2015.
22 王文陵.內(nèi)存泄漏的處理與監(jiān)測(cè).福建信息技術(shù)教育, 2005(3).
23 楊麗,郭祥昊.C語(yǔ)言常見(jiàn)內(nèi)存管理錯(cuò)誤及內(nèi)存監(jiān)控功能的實(shí)現(xiàn).新浪潮,1996,(8):21–22.
24 陳鴻杰.物聯(lián)網(wǎng)在煤礦安全生產(chǎn)應(yīng)用中監(jiān)測(cè)與控制技術(shù)研究[碩士學(xué)位論文].西安:西安電子科技大學(xué),2014.
25 寇雅楠,李增智,王建國(guó),等.計(jì)算機(jī)軟件測(cè)試研究.計(jì)算機(jī)工程與應(yīng)用,2002,38(10):103–105.
Real-Time Monitor of Dynamic Memory Based on C++
CHEN Nan
(Sinopec Geophysical Research Institute, Nanjing 211103, China)
Through the summary of the common memory errors research in the geophysical software development process, we design and implement a dynamic memory detection tool based on C/C++ by using the embedded and key function interception, which can expand and improve the compiler open interface. Through the real-time collection, classification, statistic and analysis of the heap memory usage in the running process of software, the tool achieves dynamic monitoring and detection of false memory stack. We take the NEWS software subsystem of prestack and poststack joint interpretation module process as an example to test and apply it comprehensively. The practice shows that the monitor, embedded in the software, can greatly reduce the memory leak phenomenon during the development process, and decrease the runtime memory errors caused by abnormal collapse phenomenon, and improve the stability of the application software. It also plays a strong role in the development to help tester’s in rapid location and analysis of software errors.
memory leaks; overload; detection; call stack; NEWS
國(guó)家科技重大專項(xiàng)(2011ZX05035)
2016-03-14;收到修改稿時(shí)間:2016-04-19
10.15888/j.cnki.csa.005459