999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

嵌入式Linux 下內存泄漏的檢查和解決

2020-05-20 07:15:46何愷
現代計算機 2020年11期
關鍵詞:調試程序檢測

何愷

(中國石化石油物探技術研究院,南京 211100)

0 引言

在嵌入式統一操作系統平臺(OSS)進行某程序移植中,出現了一個令人比較費解的故障,基于OSS 運行的程序在單板上長時間運行后,異常終止,并且顯示段錯誤(segment fault)。

在項目研發中,考慮到OSS 在VxWorks 操作系統、pSOS 操作系統、嵌入式Linux 操作系統等主要使用的操作系統下面都通過了產品線的測試和試用,它的性能和穩定性是很有說服力的。同時為了提高終端產品的競爭力和在操作系統方面獲得更大的資源支持,該項目把程序移植到Linux 操作系統上(硬件方案基于MIPS 芯片),操作系統支撐方面采用了OSS 平臺。

該移植項目在最初的開發結束后在PC(CPU 為x86)上基于 Redhat Linux 9.0 和 Montavisa Linux 進行了自測試,然后再移到基于ADI 提供的fusiv Linux 平臺的單板上進行系統測試。

使用GDB 調試工具對問題進行調試時,無法對多線程進行跟蹤。GDB 調試出現如下的情況:

此時繼續調試(continue),程序可以正常運行,但不能跟蹤到線程中,使用info thread 命令也不能顯示進程號、線程號等信息。

由于在Linux 操作系統方面的產品線開發經驗積累不多,同時通過網上的資料查閱,GDB 在單板上面調試POSIX 線程庫確實存在不少問題,而且基本沒有給出解答。所以在短期內通過調試工具GDB 來解決該故障是不大現實的,必須尋找其他有效的解決方法,快速對故障進行定位和解決。

1 故障原因分析

為了定位故障,一開始采用了在程序中加打印進行跟蹤的調試手段,大量的測試顯示段錯誤的出現位置并不固定,只要程序運行較長時間后,就可能出現異常終止的段錯誤。考慮到異常的出現時機比較隨機、出現位置也不固定,初步斷定是內存泄漏引起的。

1.1 內存泄漏的原因

開發人員進行程序開發的過程中使用動態變量時,需要認真把控內存管理問題,如果出現內存分配使用之后沒有進行回收或者因為程序設計的漏洞導致沒有對分配的內存進行釋放就會出現內存泄漏問題。

一般而言,內存泄漏具有隱蔽性,它不屬于直接的過錯型缺陷,比較難以檢測。如果內存泄漏在程序中反復出現,不斷積累,會降低系統整體性能,極端情況下可能使系統崩潰。

隨著應用程序的設計和開發日益復雜,在程序實現過程中處理的數據變量也大幅增加,程序中對變量的內存分配、釋放調用非常頻繁,防止內存泄漏的問題變得越來越突出,由于內存泄漏問題的隱蔽性,給開發人員、測試人員帶來解決內存泄漏類型缺陷的難題。

1.2 內存泄漏檢查的基本原理

一般情況下,在內存泄漏檢測中比較常用的算法本質上大部分都屬于程序插裝。程序插裝是在保持被測程序邏輯結構完整的基礎上,在程序的某些特定位置加入一段檢測程序,借此了解程序執行中的動態信息。它是軟件開發和測試中常用的一種基本方法,獲取程序的動態信息是其最主要的目標,它在軟件開發和測試過程中處于非常重要的地位。程序插裝技術是一個聯系靜態分析與動態信息收集的關鍵紐帶,其中插裝過程是靜態的,而信息收集過程是動態的。

基于程序插裝的內存泄漏監測算法在實現時往往需要關注兩個關鍵問題,分別是:

(1)程序插裝的位置選擇,需要選擇適當的位置,以便獲取關鍵階段信息。

(2)程序插裝的內容,即需要收集哪些動態信息。

插裝的關鍵在于能夠全面而無冗余地收集程序的動態信息,以達到揭示程序內部行為和特性的目的,需要做到緊湊精干,這一點對于實時嵌入式操作系統軟件來說非常重要。

在程序插裝內容選擇方面,需要圍繞能動態地、深入地跟蹤內存的動態分配情況這一目標。可加入一些可以跟蹤、定位內存分配與釋放的信息,例如:申請內存時,所調用的函數名稱、空間的大小、申請和釋放時間、對應程序的行號及操作系統所在模塊的位置信息等。

插裝位置的確定相對比較簡單,需要在每個內存塊申請的地方和內存塊釋放的地方進行插裝,主要是為了跟蹤內存分配、釋放情況,這樣才能做到信息全面又不冗余,更好地服務內存泄漏監測。

2 檢測方法

2.1 內存泄漏檢查一

MemWatch 是一個開放源代碼C 語言內存錯誤檢測工具。具體使用上比較簡單,需要在代碼中添加一個頭文件,并且在Makefile 的gcc 語句中進行Mem-Watch 宏的定義之后,就能進行程序中內存泄漏和錯誤的跟蹤了。MEMWATCH 能檢測雙重釋放(doublefree)、錯誤釋放(erroneous free)、沒有釋放的內存(unfreed memory)、溢出和下溢等,并且支持ANSI C,提供結果日志紀錄,對于malloc/free 引起的內存泄漏檢查十分有效的。

由于OSS 中采用了自J10 機操作系統支撐發展而來的內存分區(UB 塊)管理,只是在UB 初始化時對事前定義好的內存大小進行一次malloc,在整個OSS 進程kill 掉的時候進行釋放。所以需要對OSS_GetUB、OSS_RetUB 進行重新封裝。封裝如下:

這樣,對OSS_GetUB、OSS_RetUB 的調用就變為對malloc、free 的調用。重新編譯運行程序。MemWatch檢測出確實存在內存泄漏,但是內存泄漏行指到OSS_STATUS OSS_RetUB(VOID *pBuf)所在文件的free(pBuf)對應的所在行。

看來準確定位只有進行全部OSS_GetUB/OSS_RetUB 和malloc/free 替換。在經過替換之后,找到發生內存泄漏的語句行,問題得以解決。

優點:開源,加入工程編譯后可以直接使用,對malloc/free 導致的內存泄漏能夠有效檢測。

缺點:對于普遍使用的內存分區(UB 塊)管理代碼改動太大,加大了調試的工作量。

2.2 內存泄漏檢查二

內存監測算法一般需要跟蹤所有分配的內存塊,在監測條件被觸發時對內存塊的相關信息進行查詢,造成一定的系統開銷。常規方法在進行監測時,往往會將所有內存塊添加到鏈表結構中,若內存塊被回收則進行脫鏈操作,監測條件滿足則會收集內存塊的大小、位置、泄漏節點等信息,這種方法因為需要周期性的遍歷鏈表,有可能會導致系統開銷的不穩定,極端時會影響系統平穩運行。

針對普遍使用的內存分區(UB 塊)管理,王澤民等人提出了一種新的內存泄漏檢測算法,既能保證內存泄漏檢測的平穩性,又可以發揮UB 分區管理的優勢(避免內存碎片、充分利用系統內存資源)。

(1)算法

該算法為了避免由于引入內存泄漏監測而導致的CPU 占用時間變化劇烈,保持軟件系統的穩定性,新的監測算法設計中使用了單循環隊列的方法實現內存泄漏監測。該種算法雖然也是在時間上周期性的對內存泄漏進行監測的,但是對于每一個內存塊的掃描是均分到每個時鐘tick 里的。

在如何確定內存泄漏監測掃描周期方面,該算法有了新的嘗試。眾所周知,內存塊的使用是有一定生命周期的,那么將應用軟件中內存塊的最大使用時間作為監測時間周期會是一種好的方法,這樣可以避免頻繁的監測操作,減少對系統資源的過多占用。當然,內存塊的生命周期受具體業務類型的影響,最終的時間值可以通過應用層進行設置。

在本調試過程中,使用的最大時間是30 秒。

構建單循環隊列是該算法的關鍵,假定構建的隊列長度為L,若程序中需要分配的最大內存塊個數為M,則設置M 個內存控制描述數組。捕捉底層的時鐘中斷,每T 秒,單循環隊列的計時游標向后走一位,查找該位所指示的隊列中是否存在到期的內存塊。如存在則表明該內存塊已經超過最大有效使用時效TL,已經出現內存泄漏的情況,可以進行相應的補救操作或信息輸出。

對于TL>L 長度的內存塊,因已計算出內存塊時長TL 與L 相除所得的倍數,每次循環計時隊列頭經過時,該倍數值得減去1,直至為0,在此之后的檢查就可判斷內存泄漏并進行插入操作。插入操作時插入在原隊列的頭部。

新內存塊在循環隊列中的插入位置計算公式如下:

新內存塊的插入位置=(當前循環計時隊列頭位置+新內存塊時長與循環隊列長度相除的余數)與循環計時隊列長度相除取余。

構建的隊列長度L 取值需要注意,若L 太小容易造成倍數值的減操作過多,影響效率,L 太大則浪費存儲空間。L 的取值可以與M 的大小基本相同,以便當使用的內存塊接近M 個時,內存塊可以隨機均勻地分布到循環隊列的各數組元素中,使內存塊負載比較均衡。同時為了避免在單循環隊列中引入繁瑣的隊列操作,可以適當增大L 的值,避免TL >L 長度的內存塊。

(2)實現

在算法具體實現中,指針變量需要以循環的方式逐一指向各元素,形成的單循環隊列的每個節點又是一個單向的有序隊列。循環隊列的數據結構需要進行特定的設計,定義的數據結構中需要包含節點上監控的內存控制塊總個數、節點上第一個及最后一個內存泄漏塊的ID 等信息。

內存泄漏控制塊的數據結構需要包含內存泄漏控制塊在數組中的ID、循環隊列中前后元素的指針、內存塊的起始地址、內存塊的大小、申請行號、申請文件名等信息。在內存塊申請時,創建相應的內存泄漏控制塊結構,根據內存泄漏監測時間,將內存泄漏控制塊結構掛接到循環隊列上的對應位置。在周期性掃描過程中,若發現被掃描的循環隊列的節點上有1 個以上內存泄漏控制塊結構,則認為這些內存泄漏控制塊結構對應的UB 塊是超時未釋放的,存在內存泄漏,根據設定輸出這些UB 塊相關信息。

在循環隊列及內存泄漏控制塊的數據結構定義完成之后,內存泄漏監測算法的實現過程可以劃分為資源初始化、內存申請入鏈操作、內存回收脫鏈操作及單循環隊列的掃描等步驟。內存泄漏監測相關資源初始化這一步驟,其主要目的是構建單循環隊列,實現中需要時間源來對循環隊列進行掃描,因此準確的時間源信息獲取十分重要,在嵌入式Linux 系統中需要底層板級支撐包提供。在OSS 平臺中,本身實現的定時器管理采用了同樣的算法,所以對內存泄漏提供時間源是很方便的。

總體而言,該算法的核心是:根據實際業務情況,為分配的UB 塊設定一個最長使用時間,將該時間作為內存泄漏監測的時間周期。實現在內存泄漏時間的周期內不斷監測系統中已分配UB 塊,如果超過了最長使用時間,UB 塊依然沒有被釋放,則視為內存泄漏,進行警告并打印出相關信息。算法的重點是實現內存泄漏循環隊列的周期性掃描,使用循環隊列游標進行相應的標識,對每一個tick 進行計數。同時為分配的UB 塊設置一個內存控制單元,將其加入到單循環隊列,實現內存泄漏跟蹤,上述的這些環節構成了程序插裝的主要實現。若UB 塊正常釋放時,則移除單循環隊列上的內存泄漏控制塊,取消對應UB 塊的內存泄漏跟蹤。

通過把實現該種算法的實現文件ossmemleak.c、ossmemleak.h 加入工程,在系統初始化時加入內存泄漏相關數據結構的初始化。軟件模塊的內存泄漏有效的被檢測出來,顯示出內存泄漏時的函數、文件、行號、申請內存大小、本次申請時間,問題得以解決。

優點:可以平穩的對內存泄漏進行有效的檢測,非常適合在OSS 平臺中使用。

缺點:文件大小比MemWatch 大,同平臺相關性比較大。

2.3 內存泄漏檢查三

雖然調試工具GDB 在單板上面調試多線程存在問題,但可以使用程序產生段錯誤時的core dump 文件進行堆棧回溯,通過GDB,找到產生段錯誤的函數(其所屬的文件和行號)。為此首先要解決的是如何使運行在單板的程序在段錯誤時產生core dump 文件。

在單板上運行的程序的在段錯誤時產生core dump 文件需要進行如下的操作:

(1)使用ulimit 命令打開core dump 生成功能

#ulimit-c unlimited

(2)編譯應用時加上-g 選項,不要去掉符號表,最好是靜態編譯,這樣bt 堆棧回溯時可以查看到函數的調用層次關系。同時因為應用程序、CORE、mips_gdb都很大,最好采用nfs 方式運行程序。

(3)執行應用程序。當程序出現segment fault 時候,生成core 文件,位于被測試程序運行目錄。

如調試中的目錄:#/mnt/oss

(4)用gdb 查看core 文件,這樣可以得知程序異常退出時的錯誤地方(位于哪個文件哪一行),用p 命令可以查看當時的變量,bt 可以查看它們的堆棧情況,gdb 其他查看運行狀態的命令都可以使用。

例如#/mnt/mips_gdb/mnt/oss core

根據coredump 文件進行堆棧回溯,可以比較好的解決諸如程序宕機、內存泄漏、堆棧溢出等段錯誤的問題。但需要指出的是對于內存泄漏,它有時不能很好的定位到具體的程序異常處,例如A 處對指針重復操作,但core dump 顯示的異常位置卻是相關的另外一個地方B 的malloc 或者free 這樣的系統調用。

優點:通用性好,可以解決程序跑飛、程序異常終止等異常,對內存泄漏檢測也有一定幫助作用。

缺點:需要Linux 符號表的支持,有時不能準確定位內存泄漏所在行。

3 結語

針對基于OSS 程序移植中出現的內存泄漏問題,對問題調試、定位中使用的解決方法進行了歸納、總結。這些方法不僅可以運行在使用Linux 操作系統的內存泄漏問題中,同時前兩種方法也可以在其他操作系統下面為解決同類問題參考、借鑒。

內存泄漏問題,是開發過程中比較普遍的一個問題,往往會給測試、調試工作帶來很大的麻煩。通過這次項目的調試,認為解決內存泄漏問題,還是應該從下面兩個方面入手:

(1)開發人員的編程風格,當然這個編程風格在這里更多的不是指編程規范,多考慮一下代碼的擴展性和移植性也是避免內存泄漏的一個根本手段。

例如使用UB 塊管理

這樣的代碼在UB 塊下是可以正常運行的,但是這樣的代碼缺乏可移植性,一旦被封裝成malloc/free,就是問題代碼,而且會給調試工作帶來大麻煩。

(2)改進、完善內存泄漏檢測、定位工具,做到快速定位,有效解決。本文歸納的三種針對嵌入式Linux 的內存泄漏檢測、定位方法,通過實際的測試、調試工作,證明是有效的,可以被其他嵌入式Linux 開發借鑒以定位、解決內存泄漏問題。

猜你喜歡
調試程序檢測
“不等式”檢測題
“一元一次不等式”檢測題
“一元一次不等式組”檢測題
試論我國未決羈押程序的立法完善
人大建設(2019年12期)2019-05-21 02:55:44
基于航拍無人機的設計與調試
電子制作(2018年12期)2018-08-01 00:47:44
FOCAS功能在機床調試中的開發與應用
“程序猿”的生活什么樣
英國與歐盟正式啟動“離婚”程序程序
環球時報(2017-03-30)2017-03-30 06:44:45
無線通信中頻線路窄帶臨界調試法及其應用
電子制作(2017年19期)2017-02-02 07:08:38
小波變換在PCB缺陷檢測中的應用
主站蜘蛛池模板: 99久久精品免费看国产电影| 久久久久免费看成人影片| 欧美一区二区福利视频| 久久精品aⅴ无码中文字幕| 欧美精品高清| 午夜影院a级片| 日韩精品毛片| 亚洲黄网在线| 亚洲国模精品一区| 国产精品九九视频| 国产在线精品香蕉麻豆| 999福利激情视频| 久久久久无码精品国产免费| 国产99视频免费精品是看6| 99这里只有精品在线| 色综合国产| 亚洲人精品亚洲人成在线| 亚洲人成电影在线播放| 国产成人亚洲无码淙合青草| 中文字幕 91| 久久久久免费精品国产| 中文字幕在线视频免费| 97se亚洲综合在线| 99热这里只有成人精品国产| 亚洲成人www| 国产精品免费福利久久播放| 中文无码影院| 思思热在线视频精品| 亚洲国产黄色| 特黄日韩免费一区二区三区| swag国产精品| 亚洲人成成无码网WWW| 亚洲精品国产自在现线最新| 欧美日韩免费观看| 久久国语对白| 欧美亚洲国产精品久久蜜芽| 熟妇人妻无乱码中文字幕真矢织江| 亚洲国内精品自在自线官| 国产精品无码久久久久久| 日本免费一级视频| 人妻21p大胆| 国产精品深爱在线| 国产欧美专区在线观看| 中国精品久久| 日韩中文字幕亚洲无线码| 四虎国产精品永久一区| 激情无码视频在线看| 欧美精品二区| 播五月综合| 亚洲福利片无码最新在线播放| 99久久精品国产精品亚洲| 国产精品一区二区无码免费看片| 亚洲精品无码在线播放网站| 国产原创自拍不卡第一页| 亚洲香蕉久久| 园内精品自拍视频在线播放| 午夜精品区| AV无码一区二区三区四区| 蜜臀av性久久久久蜜臀aⅴ麻豆| 亚洲一级毛片免费观看| 亚洲不卡av中文在线| 亚洲国产日韩一区| 91视频国产高清| 精品无码国产自产野外拍在线| 久久久成年黄色视频| 2022国产无码在线| 呦视频在线一区二区三区| 免费无码AV片在线观看国产| 日韩无码黄色| 亚洲第一区在线| 欧美激情二区三区| 高潮毛片免费观看| 国产欧美日韩另类| 日韩av手机在线| 一级毛片无毒不卡直接观看| av在线人妻熟妇| 国产精品9| 亚洲国产日韩视频观看| 亚洲日韩AV无码一区二区三区人| av性天堂网| 欧洲极品无码一区二区三区| 一级爱做片免费观看久久|