都是軟件中的內存泄漏惹的禍

最近,咱們的軟件在運行過程當中,遇到了一個很詭異的問題。web

都是軟件中的內存泄漏惹的禍

軟件在一個測試同事的win7 32位系統上運行1個多小時後會閃退崩潰。奇怪的是,在測試該產品的主要測試人員的win10電腦上,則從未出現過這個狀況。windows

下面詳細介紹一下這個問題的排查過程,以及給咱們的一些啓示!服務器

一、初步分析websocket

咱們在軟件中安裝了異常信息捕獲機制,可是軟件發生閃退時,並無捕獲到有效dump文件(崩潰信息存放在dump文件中),生成的dump文件是空的!多是在導出異常上下文信息時發生了二次崩潰,因此沒有生成有效的dump文件。socket

這個問題在他電腦上出現過好幾回了。因而,讓同事將windows系統上經常使用的軟件調試利器windbg掛載到目標進程上,看看復現閃退時可否抓到有效的信息。結果問題復現後,抓到的異常上下文對應的代碼模塊基本是不可能產生異常的,因此問題排查仍是沒有頭緒!ide

忽然無心中想到,軟件是運行一兩個小時後出現的,難道是軟件中有內存泄漏?把進程的虛擬內存耗完了,致使再申請內存時都失敗了,產生了空指針,致使空指針訪問違例,致使軟件閃退。這種假設能夠解釋windbg捕獲到的不可能發生異常的代碼塊的現象了!函數

因而從新啓動軟件,觀察了任務管理器中咱們軟件對應的進程的內存佔用狀況。看到咱們軟件的進程的內存一直在增加,在運行1個多小時後居然漲到1GB多了,這下基本能夠肯定,確定是內存泄漏致使的內存被耗完,從而致使軟件再申請內存失敗了,致使訪問了空指針,致使軟件閃退了!工具

下面就是使用一些內存泄漏的檢測工具來來定位內存泄漏的模塊了!性能

二、使用騰訊的tMemMonitor內存泄漏檢測工具檢測內存泄露測試

最開始嘗試使用騰訊的tMemMonitor內存泄漏檢測工具,檢測一下內存泄漏發生在哪一個模塊中。

都是軟件中的內存泄漏惹的禍

具體的作法是,使用tMemMonitor將咱們的軟件啓動起來:

都是軟件中的內存泄漏惹的禍

讓軟件運行一個多小時,讓軟件產生1GB以上的內存泄漏,而後關閉軟件,若是檢測到內存泄漏就會彈出生成檢測報告的提示,打開報告就能夠看到檢測結果了。

注意,tMemMonitor內存泄漏檢測工具只能檢測release版本的程序,被檢測程序必須由tMemMonitor啓動,而且被監測程序在退出時必須是正常退出的。若是關閉軟件時發生了崩潰,tMemMonitor是不會生成內存泄漏報告的。

檢測報告中會顯示發生內存泄漏的dll或exe的模塊名,而且會將相關的函數調用堆棧打印出來,好比:

都是軟件中的內存泄漏惹的禍

但實際跑下來,看到檢測報告,並無看到有用的信息,檢測到泄漏內存的都比較小,和實際泄漏的內存大小相差甚遠!難道不是用戶態的內存泄漏?是內核態的內存泄漏?

三、使用windbg檢測內存泄漏

使用tMemMonitor工具分析不出來,因而又嘗試使用windbg分析了一把。使用此方法以前,要預先安裝好windbg工具。最新版本的windbg是從內置在微軟官方的SDK中的,能夠自行到微軟的官方網站上下載安裝。

此內存泄漏檢測方法,會用到windbg安裝路徑下的gflags.exe和umdh.exe程序,以下所示:

都是軟件中的內存泄漏惹的禍

具體的操做步驟是:

1)打開cmd窗口,切換到windbg的安裝目錄中,好比個人安裝路徑是:C:\Program Files\Windows Kits\10\Debuggers\x86。

2)先使用命令設置用戶態函數棧回溯標記:gflags /i xxxxxxxxx.exe +ust,具體含義能夠以「gflags /?」查看gflags相關命令行的參數說明:

都是軟件中的內存泄漏惹的禍
都是軟件中的內存泄漏惹的禍

3)使用umdh.exe將時刻1時的堆內存分配狀況輸出到日誌文件中:umdh.exe -pn:xxxxxxxxx.exe -f:E:\log1.txt。其中,umdh.exe是windows debug tools 下的一款命令行工具,它的全程是User Mode Dump Heap 這個工具會分析當前進程在堆上分配的內存。可使用「umdh /?」查看umdh.exe支持的命令行參數,以及如何使用的:

都是軟件中的內存泄漏惹的禍

而後讓程序運行一個多小時後,讓程序有足夠多的內存泄漏,而後再用命令:umdh.exe -pn:xxxxxxxxx.exe -f:E:\log2.txt,導出時刻2時的堆內存分配使用狀況。

4)使用命令:umdh.exe E:\log1.txt E:\log2.txt -f:E:\result.txt,比較兩個時刻中間的時間段的堆內存的增加及使用狀況,找出可能出現內存泄漏的地方:

都是軟件中的內存泄漏惹的禍

這彷佛仍是有問題,明明泄漏了1GB多的內存,怎麼檢測結果中最多泄漏的那項計算出來泄漏的內存才200MB,相差的比較多的,看來windbg彷佛也不可信啊!

四、使用代碼分塊註釋的辦法,定位到發生內存泄漏的模塊

問題仍是沒查出來,這個就比較頭疼了,軟件立刻要對外發布正式商用版本了,這個問題必需要解決啊!

最後沒辦法,只能採用逐步註釋代碼的方法,看看可否定位內存泄漏發生在哪一個模塊中。經屢次嘗試發現,與dcs數據協做模塊的庫有關係。而後查看了一下dcs服務器的鏈接狀態,服務器連不上,底層一直在不斷的定時重連,難道是每次重連失敗後沒有釋放socket套接字等資源致使的內存泄漏?

因而找到相關模塊的負責同事,讓他們排查,排查下來後發現,確實是服務器重連失敗後沒有將相關資源釋放掉致使的內存泄漏(使用websocket和服務器通訊的)!

後來在我本身的兩臺電腦上驗證了一下,軟件運行在我win7 32位電腦上是有內存泄漏的,但在我另外一臺win7 64位系統上則沒有內存泄漏。在測試同事的win10系統上,也詳細觀察了,win10系統上竟然沒有內存泄漏,軟件運行一切正常!這個內存泄漏難道是和操做系統是強相關的?

五、進一步研究確認

知道大概的緣由以後,我又用windbg和tMemMonitor都從新檢測了一下內存泄漏,看看哪一個工具更好用,定位的更準確!

咱們選擇檢測的時間段內,軟件已經佔用了1.15GB的內存,內存泄漏估計得有900MB左右了。

此時windbg分析出來的內存泄漏模塊確實是對的,以下所示:

都是軟件中的內存泄漏惹的禍

可是泄漏的內存只有200MB左右,這和實際的內存泄漏大小有很大的出入。當前windbg分析出的內存泄漏是用戶態的,可能有部分泄漏發生在程序的內核態?

而騰訊的tMemMonitor和windbg比要遜色很多,tMemMonitor不只檢測出的泄漏內存大小比實際泄漏大小要小不少,並且根本沒有定位到發生內存泄漏的模塊。因此,windbg仍是要強大很多的。

經後來驗證,在另外一臺的win7 64位系統中,以前之因此沒有內存泄露,是由於這臺機器上登陸平臺的帳號是沒有dcs服務的權限,就不會登陸dcs服務器,就不會觸發dcs服務器的重連。而本例中的內存泄漏就是dcs重連失敗後沒有清理相關資源致使的。後來使用一個有dcs服務權限的帳號在這臺win7 64位系統中登陸咱們的軟件,一樣也出現了內存泄漏。

但一樣的代碼、一樣的軟件在win10系統中卻沒有內存泄漏,經過打印日誌能夠肯定win10系統中也觸發了dcs服務器的重連了,這多是win10系統的內存管理機制和win7不一樣引發的吧!

六、總結

遇到問題後,要進行深刻細緻的研究,要搞清楚各類狀況的前因後果!在詳細的研究過程當中要多思考多驗證,會有新的發現和新的收穫!

【編輯推薦】

  1. 談談關於存儲技術的入門
  2. IBM宣佈SSD神優化技術:性能、可靠性提高3倍 延遲下降50倍
  3. 五個從存儲類內存中受益的應用程序
  4. JVM性能調優Java內存區域與內存溢出異常
  5. 在線研討會 :Pure Storage 以全閃存技術優化VDI的用戶體驗

【責任編輯:華軒 TEL:(010)68476606】

相關文章
相關標籤/搜索