腳本內存泄漏
Ⅰ 關於win7系統環境下,EXE程序文件損壞問題
錯誤提示:文件或路徑名不正確。選擇忽略,又彈出提示:fatal error:exception code=c0000005
先轉一個致命錯誤=C0000005吧。
小聊 "致命錯誤=C0000005 "
這份帖子主要在講述「致命錯誤——C0000005」,它是什麼,為什麼會出現,何種情況下將出現,以及如何避免之。請根據您的口味選擇是否瀏覽之。
昨夜又見論壇上尋問C0000005的帖子,是關於Visual Foxpro 9.0 版本的,這引起了我的注意。
本以偷懶的態度草草回復之,然而接下來網友的追問使我自知偷懶的後者便是語義表達不到位,便索性連夜寫下此主題帖。但仍以簡練為主,請大家多擔待!
c0000005錯誤發生的誘因主要分為四大類:
1、自由表存儲載體的缺陷(主要體現在VCX、VCT,SCX和SCT上)。
2、第三方監控性質的軟體(如:防毒軟體在內存即時監控狀態下、詞霸在全屏拾取模式下等);
3、Visual Foxpro 自身的代碼漏洞;
4、硬體因素。
先說第一大類:
同數據表一樣,在Visual Foxro 9.0 版本中,自由表也支持了原子事務機制,這並非主要是為了滿足客戶的需要,而以穩定VFP9自身為主。我們都知道類與表單的代碼多以物理形式為自由表的VCX、VCT,SCX和SCT文件格式存儲,在IDE設計模式下,代碼被VFP後台以獨占的、開放式自由表緩沖的模式存取。然而您應該敏感地注意到:自由表是不支持事務機制的(低於9.0版本的Visual Foxro)。也就是說,遇到停電或操作系統異常時,它們同樣會面臨表頭損壞、低級鏈接錯誤、記錄指針錯誤偏移的風險。Microsoft Visual Foxpro 開發組沒有將VCX、SCX設計為依賴於資料庫的數據表的形式,原因不難理解——如果一個表單文件中,包括表單本身在內的任何一個控制項都不依賴於用戶自定義派生類的話,那麼該文件應該可以被獨立地拷貝與打開。
如下的常識我們都需要知道:
無論是在設計模式還是在運行模式下,Visual Foxpro的Runtime會隨時將客戶腳本讀取到內存體中,並交由詞法分析器、語法分析器和語義分析器來分析、解釋、處理這些代碼。
(通常情況,在編輯模式下,我們的腳本代碼已經被Visual Foxpro詞法分析器進行了第一遍的過濾;在編輯完一個prg或表單或類文件後,若按下Ctrl+W組合鍵將在保存它之前調用語法分析器來試圖檢查其中的錯誤(注意「詞法」分析器與「語法」分析器的不同),然後程序界面將自動被關閉;而若按下Ctrl+S組合鍵保存後,再手動退出時,這種情況下將不會調用語法分析程序。)
如果你的腳本保存在自由表形式的SCX、SCT、VCX、VCT文件中,Visual Foxpro會通過表的記錄指針提取對應備注文件里的程序腳本(那裡或許包含了某些事件或方法的代碼)。首先,Visual Foxpro 的底層通過調用C語言的sizeof()來判斷位元組的長度,根據長度提取位元組,將其存放到字元類型的數組中,最後將長度的返回值與該存放實際代碼的數組以參數的形式傳遞給語義分析器來解釋執行。然而在一些情況下,會發生sizeof()判斷的位元組長度與實際的長度不一致的情況。
倘若sizeof()判斷的位元組長度與實際的長度不一致,將會發生內存的溢出,這個致命錯誤被Visual Foxpro異常處理器捕獲後,將拋出「致命錯誤-C0000005」的信息。
「致命錯誤=」是字元常量,「c0000005」是一個變數,c0000005不是VFP的錯誤編碼,而是得到Windows消息環所傳遞過來的錯誤消息參數的半加工品。它的原始狀態是16進制的0xC0000005,VFP通過相關的轉換函數轉換成字元串的形式,以便通過界面描述給用戶。
那麼什麼情況下會出現sizeof()判斷的位元組長度與實際的長度不一致的情況呢?主要有兩方面的主導因素。
1、我們前面鋪墊過了,VCX、VCT,SCX和SCT文件都是自由表,都有可能在設計時被無意的損壞。
倘若表頭被損壞,您會在試圖打開它們的時候收到VFP系統的無法打開該表單的信息;但倘若低級鏈接錯誤、記錄指針錯誤偏移,您就不會得到任何VFP的提示,因為VFP系統自己也不知道這一點,就像您一樣。於是直到程序運行時,才會收到令人驚愕的致命錯誤信息——語義分析器工作時內存被溢出。
在一些「致命錯誤-C0000005」的信息框中,您會收到似乎更詳細些的信息,指示您程序出錯的地方。那通常是包含在SCX、SCT或VCX、VCT里某些行的代碼。
千萬不要被誤導,並不是您的程序代碼編寫有問題,而是隱藏在標識符之外的、看起來好像是空格、回車的空白段,那裡隱藏了低級鏈接的錯誤、或Unicode的錯位排序(下面馬上就會講述到),用Shift+方向鍵將整行全選,然後按Delete鍵刪除之,最後老老實實地將原行代碼重新書寫一遍即可(切記:用Shift+方向鍵將整行全選,然後將該整行徹底清除)。
2、Unicode
從Windows98升級過來的VFP程序員似乎都曾有過這樣的困惑:為什麼Windows2000以上版本的VFP程序會如此的不穩定,以至於頻繁出現「致命錯誤——C0000005」?
Visual Foxpro的詞法掃描器大概是這樣工作的:詞法掃描器分析代碼腳本的時候,先要判斷一下 下一個被掃描的Token是否為空白標記。若是,則看該空白標記是Tab標記還是回車標記,或者是分隔符或其它的佔位符;若不是,則判斷該Token是單位元組還是雙位元組字元,這種機制在基於Unicode的Windows版本中,有時會遇到標識符號的錯位。
您現在上網用的計算機的操作系統是WIN2000或WinXP嗎?如果是,不妨親自做這樣一個試驗:
打開記事本程序,輸入「聯通」,然後保存後關閉該文本,再重新開打,看到什麼了?標識符號被錯位了!
是的,當年WIN2000操作系統的流行時,Visual Foxpro開發組並沒有徹底改正語義分析器代碼的漏洞。
好的,第一大類我就闡述完了。如何避免它呢?
*--------------
總的應該說很麻煩,有兩種途徑供您選擇:
1、修改VCX、SCX表國際代碼頁的編碼,將簡體中文編碼改為英文編碼;
2、我所推薦的方法是盡量用prg。你可能會認為這樣做很麻煩,但作為程序員,您應該更加專業一些。您可以備份可視化的表單或類文件,但在程序正式發布前,最好最大限度地轉化為prg程序。倘若以後需要修改程序,通過備份的表單或類文件進行可視化編輯,然後再次轉化為prg發布之。
對於已經開發好的項目,就沒有必要大興土木地全部將Vcx、Scx轉化為Prg了,但您應該著重關注一下主菜單Mnx文件,及控制項(尤其是圖片)特別多的表單。或許,您曾遇到過這樣令人匪夷所思的問題:在運行exe文件時,為什麼有時候一切正常,而有時候卻產生致命異常——要知道開發人員根本就沒改任何的代碼呀?
下面我將剖析上面的問題:
在用菜單編輯器進行菜單定義時,Visual Foxpro系統將產生四個對應文件:一個自由表、前者的備注文件,一個程序文件(mpr)及它的執行格式文件(mpx)。
如果您用 Do Menu XXX.mnx 的方式調用主菜單時,.mnx與.mnt兩文件將被包含至工程中去,在exe執行時,以提取自由表記錄的形式解釋程序。
但mnx模式存在著一個致命的缺欠,就是Visual Foxpro 在申請堆棧時的預定空間量相對prg的程序文件要小許多。通常這沒什麼問題,但你要知道並不是每次Visual Foxpro 都能如願地向Windows操作系統申請到預定的空間值,有的時候它所獲得的堆棧數目會少一些,甚至恰巧會小於菜單初始化時所需要佔用的空間量。這就是為什麼有時候exe第一次運行時正常,退出後再次運行時偶爾會出現「致命錯誤-c0000005」的原因。
請您以 Do XXX.mpr 的形式直接調用程序文件形式的mpr,就能夠很好地避免之。因為在默認情況下,Visual Foxpro 為程序文件所申請的堆棧數遠遠大於mnx,即便是Visual Foxpro沒有從Windows操作系統中得到預定數目的空間,然而比起 定義存儲prg內腳本的字元型數組的長度來說,也綽綽有餘了。
另外,一個存儲了大量控制項與圖片信息的表單,同樣會遇到與菜單文件相似的情形——即Visual Foxpro 所獲得的堆棧數小於表單初始化時所需要的數目,從而造成內存的溢出。
順便告訴您一個小竅門:
在IDE設計模式下,我們或許會突然遇到「致命錯誤-C0000005」襲擊,因為表單是以獨占的、開放式自由表緩沖的模式交互的,所以此前未經保存的信息都將被丟失,這您是知道的,通過剛才的講述,您還知道了這或許會面臨表被損壞的風險,從而進入了一個「致命錯誤-C0000005」潛在引發今後「致命錯誤-C0000005」故障的惡性循環。
小竅門就是,您千萬不要條件反射地去觸擊那個「確定」按鈕!那不過只是Visual Foxpro系統所捕獲的異常罷了,它不是真「致命」的,Visual Foxpro系統仍在運轉中,也就是說,它還在正常地接收著Windows操作系統不斷發送來的消息。這時,請您點開Windows桌面最左下角的「開始」按鈕,選擇「重新啟動計算機」或「關閉計算機」,Windows在試圖關閉電腦前,會先檢查是否有尚在運行中的應用程序,它會發現一個叫Fox的先生尚未退場,於是便發送清場的消息給Foxpro,Visual Foxpro其實還在正常的運轉中,它接收到這條消息後,會調用自身的退出機制試圖退出,而自身的退出機制會發現尚有正在編輯的表單,便會發出「需要保存修改嗎?」的詢問消息,這時候,您選擇保存,就可以了!
千萬注意了!這段過程大概只有5秒鍾的時間!因為為了防止死循環的情況出現,Windows會在等待幾秒鍾對方不應答的情況下強行終止程序,那時候,就真正退出整個Windows系統了。所以您一定要眼疾手快!
第二大類是第三方監控性質的軟體。如:防毒軟體在內存即時監控狀態下、詞霸軟體在全屏拾取模式下等。其實防毒軟體本身並不與VFP產生沖突,但有一個例外,就是內存即時監控(請注意:防毒有許多即時監控,唯有內存即時監控才會與有時候與VFP發生沖突)。
所謂內存即時監控並不是去讀取內存條中的數據,誰也沒這么大的本事,它的原理就是專門關注於Windows系統目錄下的system32子目錄中的程序文件在運行中的狀態。
我們知道,在Visual Foxpro 8.0 版本以前,其運行時刻文件是安裝在system32目錄中的;而向最終客戶發布你的應用程序時,默認情況下,無論是VFP什麼版本,其運行時刻文件均會被拷貝到system32目錄中去。
防毒軟體的內存即時監控的工作原理是這樣的(這是瑞星公司首創的,瑞星軟體也是狐友受害最深的):1、它會在Windows後台運行一個類似於Windows的模擬機(這有點像任天堂游戲模擬機和一些手機模擬機,還有現在時髦的linux下的Windows模擬機);2、它運行一個循環,挨個監視system32目錄下的exe及dll文件是否被調用;3、倘若被調用,就拷貝一份到瑞星自己創建的隱含、系統目錄中去,然後在那個模擬機中運行之,以便模擬其在Windows實際運行中的狀態;4、在模擬運行中,看它是否有病毒發作的特徵;5、如果有,就查找病毒特徵碼資料庫;6、若在資料庫中,找到了對應的特徵碼,便確定特徵碼所對應的病毒名稱,否則,就按未知名的新病毒處理(這就是為什麼有的VFP加密軟體會被防毒軟體誤報病毒)。
由於VFP應用程序與運行時刻DLL庫交互的太頻繁了,使防毒軟體的那個循環程序不斷捕捉到VFP運行時刻庫在進行新的數據響應,防毒軟體便不斷地試圖拷貝它,以便進行新一輪的模擬。但你知道,無論是DBF還是SCX等等,只要是獨占方式打開的(SCX與VCX總是被獨占的,而DBF取決於你的設計),就不能被其它的程序所訪問。但在Windows操作系統中,防毒軟體所調用拷貝程序的系統優先順序要高於你的程序的優先順序,所以有時你的VFP程序會最終產生致命錯誤。
如何避免呢?你可以簡單地關閉防毒軟體,但如果讓客戶也像你這樣做的話,就有霸道之嫌了。
聰明的你恐怕現在已經想到了:只要在發布你的應用程序時,將那些運行時刻庫放到應用程序目錄下就可以了!
同樣,詞霸軟體本身也不會與你的程序發生沖突,只是在全屏取詞的模式下才會如此。不過你的用戶幾乎不會遇到,因為你的程序幾乎不會讓他們在程序界面狀態下直接打開某個數據表——僅在詞霸的全屏取詞程序試圖通過獨占模式下的數據表的窗口句柄,來訪問裡面的文本屬性時,才會與其獨占模式發生沖突。
第三大類是Visual Foxpro 自身的代碼漏洞。比如VFP6.0版本的Textbox控制項等等。現在版本的VFP,這樣的錯誤少多了。關於Visual Foxpro 自身的代碼漏洞導致c0000005異常的話題,早已被論壇上諸多的高手反復總結過了,我們的話題就不再展開了。
第四大類是硬體因素。
有些細節問題是最不被人所注意的。但其足以鑄成大過。
「致命錯誤C0000005」是內存泄漏的症狀,而不僅僅是內存溢出、除零(這就是Visual Foxpro 自身的代碼Bug所導致的結果),還有一個原因就是申請到的堆棧意外不足。
在用電高峰期(例如夏季、或晚間的黃金時段),電壓的突然不穩定,或許會非常微小,不至於迫使計算機意外重啟,但或許會導致VFP系統在通過Windows消息機制向內存體申請堆棧時,得到Windows意外的反饋。
除了說服您的客戶使用UPS外,您應該檢查用電的負荷情況,比如檢查列印機或台燈是否與計算機電源線一起接在一個多功能插座上,應該盡量避免這樣,一些老式的列印機,在列印作業時會消耗很大的電流。
------------------------------------------
C000005排除一例
問題:
在使用菜單項呼叫這個表單的時候,出現 C000005 錯誤。
但在表單里呼叫這個表單的時候,一切正常。
接下來的菜單項里的呼叫全部正常。也就是說,一定要先由表單呼叫一次這個表單,否則不管什麼時候都發引發 C000005 錯誤。
原本以為小問題,結果,動用人力物力都無法排除。
排錯第 1 步:菜單生成器有缺陷,自己動手寫一個代替它。解決了嗎?沒有
排錯第 2 步:生成的菜單其實也是過程文件,改為用過程呼叫。解決再現了嗎?是的。
*-- 重新確定問題源:在使用過程呼叫這個表單的時候,出現 C000005 錯誤。
排錯第 3 步:重建項目,重新編譯類庫。解決了嗎?沒有。
排錯第 4 步:更改表單名,更改控制項名,注釋所有事件,方法,過程。解決了嗎?沒有。
排錯第 5 步:更改控制項在表單的載入順序,全部顛倒過來。解決了嗎?沒有。
排錯第 6 步:移去數據環境。解決了嗎?沒有。
排錯第 7 步:逐一從表單上移去控制項,問題解決了嗎?全部控制項移除,問題解決。·¥#%#¥
排錯第 8 步:新建空表單,從備份的表單上逐一復印控制項,問題再出了嗎?是的。
排錯第 9 步:刪除所有控制項,僅留下最後那個復制過來的控制項,問題再現了嗎?是的!
重新確定問題源:類庫內部出問題。
排錯第 10 步:NODEFAULT 阻止所有事件與方法。問題解決了嗎?沒有!
重新確定問題源:不是方法或事件引發的這個錯誤。因為根本沒有執行任何代碼。
排錯第 11 步:更改部份有意義的內部私用屬性名稱,問題解決了嗎?沒有!
排錯第 12 步:決定要更改外部公用屬性名與方法名……慢,你先殺了我吧!不可能,整個程序嵌入的事件設定與引用會全部消失,程序將崩潰。不如不排除這個錯誤。
排錯第 13 步:苦思……為什麼以前不會呢?
排錯第 14 步:解開舊程序的類,逐一比較。正常。除了某些屬性為了慎重,隱藏了起來。
排錯第 15 步:那舊的類來代替它嗎?這是不可能的。只會向上升級那有向下降級的。
排錯第 16 步:無奈,順手將隱藏的屬性恢復為公共。
排錯最後一步:奇跡出現,C00005 錯誤被處理!總耗時:16 小時。
復制備份的完整表單,編譯,,,,一切正常。
將屬性仍設為私有。正常。不信邪,再次設為隱藏。問題再見!!
活見鬼!!哪位兄弟能告訴我這是為什麼?是 VFP 的問題還是程序的問題?
為什麼類的部份屬性設為隱藏並且一行代碼也未進行操作,在使用過程呼叫會出 C000005 錯誤,在表單對象中的呼叫就不會?看來我們只有一個選擇,慎用屬性與方法隱藏。
唉,一天就這么過去了……好睏。
[hunter__fox ]
從排除過程看來,出現這個C000000005錯誤的原因是這樣的:
當隱藏了系統默訂的屬性與方法(以後統稱內容)後,在過程中調用時,因為系統環境中沒有同樣的基類存在,第一次建立這些對象的實例須要訪問一些被隱藏的內容,因此出現了C000000005錯誤------訪問的內存被禁止。
而在通過表單調用時,那些被隱藏的內容在已有的表單及其控制項中已經存在,系統中已經存在關於這些類的這些方法,因此,資源已經存在,就不會出現C000000005錯誤。
驗證這一點,可以這樣來試一下:
建立一個表單,其中僅有一個控制項:Command1用於打開表單2。
表單2中使用一個自定義類Grid,它的屬性 "RowSource "和 "RowSourceType "設為隱藏。
菜單就不用建了,因為一定會產生C000000005錯誤。
如果通過表單1調用表單2時產生了C000000005錯誤,則完全是因為隱藏屬性的原因引起這一錯誤的。若沒有產生這一錯誤,則表明,隱藏的內容並不是這燈C000000005錯誤的根源。
因為在表單1沒有任何控制項具有RowSource和RowSourceType屬性,因此,在建立表單2的實體時,Grid控制項的這兩個屬性無論如何都沒有資源可供參考,如果僅是因為隱藏屬性的問題,這里必然會產生同樣的錯誤。
VFP報表中使用圖形時常出現這樣的問題,如果能夠確定是因為隱藏屬性還是其它的根本原因,對於從根本上解決這類問題將是大有作用的。
[coolyylu]
我認為問題的根本:對於屬性隱藏,私有,公共的設置
對於老的類的某些屬性你設置隱藏
1。這些隱藏屬性是系統的還是你自己定義的?
在vfp裡面,正常情況下,你設置一個屬性為隱藏,那麼系統一般會提示你「該屬性找不到」。有些特殊的情況,當在你的系統(已經打開的窗口)佔用了很多內存,這些找不到屬性會引起系統崩潰(c00005的錯誤)。這種情況不多見。那麼即使你設置的系統的屬性為隱藏,那麼也只會提示找不到。對於recordsource,rowsource等屬性,很有可能引起c00005的錯誤,這個我不是太清楚。
2。你的vfp升級到pack5沒有(如果是vfp6),如果是vfp7請升級到pack1。
Ⅱ 怎樣發現內存泄露
一、內存泄漏的檢查方法:
1.ccmalloc-Linux和Solaris下對C和C++程序的簡單的使用內存泄漏和malloc調試庫。
2.Dmalloc-Debug Malloc Library.
3.Electric Fence-Linux分發版中由Bruce Perens編寫的malloc()調試庫。
4.Leaky-Linux下檢測內存泄漏的程序。
5.LeakTracer-Linux、Solaris和HP-UX下跟蹤和分析C++程序中的內存泄漏。
6.MEMWATCH-由Johan Lindh編寫,是一個開放源代碼C語言內存錯誤檢測工具,主要是通過gcc的precessor來進行。
7.Valgrind-Debugging and profiling Linux programs, aiming at programs written in C and C++.
8.KCachegrind-A visualization tool for the profiling data generated by Cachegrind and Calltree.
9.IBM Rational PurifyPlus-幫助開發人員查明C/C++、託管.NET、java和VB6代碼中的性能和可靠性錯誤。PurifyPlus 將內存錯誤和泄漏檢測、應用程序性能描述、代碼覆蓋分析等功能組合在一個單一、完整的工具包中。
二、內存泄漏的簡單介紹:
內存泄漏也稱作「存儲滲漏」,用動態存儲分配函數動態開辟的空間,在使用完畢後未釋放,結果導致一直占據該內存單元。直到程序結束。(其實說白了就是該內存空間使用完畢之後未回收)即所謂內存泄漏。
內存泄漏形象的比喻是「操作系統可提供給所有進程的存儲空間正在被某個進程榨乾」,最終結果是程序運行時間越長,佔用存儲空間越來越多,最終用盡全部存儲空間,整個系統崩潰。所以「內存泄漏」是從操作系統的角度來看的。這里的存儲空間並不是指物理內存,而是指虛擬內存大小,這個虛擬內存大小取決於磁碟交換區設定的大小。由程序申請的一塊內存,如果沒有任何一個指針指向它,那麼這塊內存就泄漏了。
Ⅲ 求教為什麼寫關於Socket的腳本Unity3D就卡死
我說一下我的想法,看看對你是不是用。
第一,如果你的客戶端socket在連接伺服器的時候是在主線程做的,那麼在報告連接伺服器之前,下層會有多次嘗試的情況,這就是會卡死的原因。我自己遇到這個問題的時候有關連接伺服器的部分開了一個專門的線程來處理,沒有出現卡死的情況。
第二,就是有關資源的問題。例如你的程序不小心在主線程弄了個死循環、其他資源或者腳本導致的內存泄漏等等原因都會使你的程序卡死,你看一下是不是這些東西間接導致的你的soclet卡死了。
第三,不知道你的伺服器使用什麼做的,伺服器程序並發性怎麼樣,還有硬體能不能支持都需要考慮,是不是這一塊卡死的。
如果不麻煩,你可以多說一點關於這個卡死的具體情況,我看看我知不知道。
Ⅳ loadrunner錄制的腳本會導致內存泄漏嗎
內存泄漏是待測系統的問題
loadrunner 只不過是通過施壓 讓該問題暴露出來
Ⅳ 怎麼排查這些內存泄漏
最原始的內存泄露測試
重復多次操作關鍵的可疑的路徑,從內存監控工具中觀察內存曲線,是否存在不斷上升的趨勢且不會在程序返回時明顯回落。
這種方式可以發現最基本,也是最明顯的內存泄露問題,對用戶價值最大,操作難度小,性價比極高。
MAT內存分析工具
2.1 MAT分析heap的總內存佔用大小來初步判斷是否存在泄露
在Devices 中,點擊要監控的程序。
點擊Devices視圖界面中最上方一排圖標中的「Update Heap」
點擊Heap視圖
點擊Heap視圖中的「Cause GC」按鈕
到此為止需檢測的進程就可以被監視。Heap視圖中部有一個Type叫做data object,即數據對象,也就是我們的程序中大量存在的類類型的對象。在data object一行中有一列是「Total Size」,其值就是當前進程中所有Java數據對象的內存總量,一般情況下,這個值的大小決定了是否會有內存泄漏。可以這樣判斷:
進入某應用,不斷的操作該應用,同時注意觀察data object的Total Size值,正常情況下Total Size值都會穩定在一個有限的范圍內,也就是說由於程序中的的代碼良好,沒有造成對象不被垃圾回收的情況。
所以說雖然我們不斷的操作會不斷的生成很多對象,而在虛擬機不斷的進行GC的過程中,這些對象都被回收了,內存佔用量會會落到一個穩定的水平;反之如果代碼中存在沒有釋放對象引用的情況,則data object的Total Size值在每次GC後不會有明顯的回落。隨著操作次數的增多Total Size的值會越來越大,直到到達一個上限後導致進程被殺掉。
2.2 MAT分析hprof來定位內存泄露的原因所在。
這是出現內存泄露後使用MAT進行問題定位的有效手段。
A)Dump出內存泄露當時的內存鏡像hprof,分析懷疑泄露的類:
B)分析持有此類對象引用的外部對象
C)分析這些持有引用的對象的GC路徑
D)逐個分析每個對象的GC路徑是否正常
從這個路徑可以看出是一個antiRadiationUtil工具類對象持有了MainActivity的引用導致MainActivity無法釋放。此時就要進入代碼分析此時antiRadiationUtil的引用持有是否合理(如果antiRadiationUtil持有了MainActivity的context導致節目退出後MainActivity無法銷毀,那一般都屬於內存泄露了)。
2.3 MAT對比操作前後的hprof來定位內存泄露的根因所在。
為查找內存泄漏,通常需要兩個 Dump結果作對比,打開 Navigator History面板,將兩個表的 Histogram結果都添加到 Compare Basket中去
A) 第一個HPROF 文件(usingFile > Open Heap Dump ).
B)打開Histogram view.
C)在NavigationHistory view里 (如果看不到就從Window >show view>MAT- Navigation History ), 右擊histogram然後選擇Add to Compare Basket .
D)打開第二個HPROF 文件然後重做步驟2和3.
E)切換到Compare Basket view, 然後點擊Compare the Results (視圖右上角的紅色」!」圖標)。
F)分析對比結果
可以看出兩個hprof的數據對象對比結果。
通過這種方式可以快速定位到操作前後所持有的對象增量,從而進一步定位出當前操作導致內存泄露的具體原因是泄露了什麼數據對象。
注意:
如果是用 MAT Eclipse 插件獲取的 Dump文件,不需要經過轉換則可在MAT中打開,Adt會自動進行轉換。
而手機SDk Dump 出的文件要經過轉換才能被 MAT識別,Android SDK提供了這個工具 hprof-conv (位於 sdk/tools下)
首先,要通過控制台進入到你的 android sdk tools 目錄下執行以下命令:
./hprof-conv xxx-a.hprof xxx-b.hprof
例如 hprof-conv input.hprof out.hprof
此時才能將out.hprof放在eclipse的MAT中打開。
手機管家內存泄露每日監控方案
目前手機管家的內存泄露每日監控會自動運行並輸出是否存在疑似泄露的報告郵件,不論泄露對象的大小。這其中涉及的核心技術主要是AspectJ,MLD自研工具(原理是虛引用)和UIAutomator。
3.1 AspectJ插樁監控代碼
手機管家目前使用一個ant腳本加入MLD的監控代碼,並通過AspectJ的語法實現插樁。
使用AspectJ的原因是可以靈活分離出項目源碼與監控代碼,通過不同的編譯腳本打包出不同用途的安裝測試包:如果測試包是經過Aspect插樁了MLD監控代碼的話,那麼運行完畢後會輸出指定格式的日誌文件,作為後續分析工作的數據基礎。
3.2 MLD實現監控核心邏輯
這是手機管家內的一個工具工程,正式打包不會打入,BVT等每日監控測試包可以打入。打入後可以通過諸如addObject介面(通過反射去檢查是否含有該工具並調用)來加入需要監控的檢測對象,這個工具會自動在指定時機(如退出管家)去檢測該對象是否發生泄漏。
這個內存泄露檢測的基本原理是:
虛引用主要用來跟蹤對象被垃圾回收器回收的活動。虛引用必須和引用隊列(ReferenceQueue)聯合使用(在虛引用函數就必須關聯指定)。當垃圾回收器准備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,自動把這個虛引用加入到與之關聯的引用隊列中。程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。
基於以上原理,MLD工具在調用介面addObject加入監控類型時,會為該類型對象增加一個虛引用,注意虛引用並不會影響該對象被正常回收。因此可以在ReferenceQueue引用隊列中統計未被回收的監控對象是否超過指定閥值。
利用PhantomReferences(虛引用)和ReferenceQueue(引用隊列),當PhantomReferences被加入到相關聯的ReferenceQueue時,則視該對象已經或處於垃圾回收器回收階段了。
MLD監控原理核心
目前手機管家已對大部分類完成內存泄露的監控,包括各種activity,service和view頁面等,務求在技術上能帶給用戶最順滑的產品體驗。
接下來簡單介紹下這個工具的判斷核心。根據虛引用監控到的內存狀態,需要通過多種策略來判斷是否存在內存泄露。
(1)最簡單的方式就是直接在加入監控時就為該類型設定最大存在個數,舉個例子,各個DAO對象理論上只能存在最多一個,因此一旦出現兩個相同的DAO,那一般都是泄露了;
(2)第二種情況是在頁面退出程序退出時,檢索gc後無法釋放的對象列表,這些對象類型也會成為內存泄露的懷疑對象;
(3)最後一種情況比較復雜,基本原理是根據歷史操作判斷對象數量的增長幅度。根據對象的增長通過最小二乘法擬合出該對象類型的增長速度,如果超過經驗值則會列入疑似泄露的對象列表。
3.3 UIAutomator完成重復操作的自動化
最後一步就很簡單了。這么多反復的UI操作,讓人工來點就太浪費人力了。我們使用UIAutomator來進行自動化操作測試。
目前手機管家的每日自動化測試已覆蓋各個功能的主路徑,並通過配置文件的方式來靈活驅動用例的增刪改查,最大限度保證了隨著版本推移用例的復用價值。
至此手機管家的內存泄露測試方案介紹完畢,也歡迎各路牛人交流溝通更多更強的內存泄露工具盒方案!
騰訊Bugly簡介
Bugly是騰訊內部產品質量監控平台的外發版本,其主要功能是App發布以後,對用戶側發生的Crash以及卡頓現象進行監控並上報,讓開發同學可以第一時間了解到App的質量情況,及時機型修改。目前騰訊內部所有的產品,均在使用其進行線上產品的崩潰監控。
Ⅵ javascript setTimeout遞歸會造成內存泄漏嗎
前端開發,熱愛生活
var call = function(x) {
console.log(x++);
setTimeout(function() { call(x); }, 1);
};
call(0);
以這段代碼為例,的確x這個變數會一直存在在內存之中,但這么一個變數還不至於讓內存達到溢
出。並且可以在chrome Dev Tool中模擬一次垃圾回收結果:
可以看到js heap一直在增加可以看到js heap一直在增加
但是console 依然在跑,其實這已經算是內存泄露了。但是console 依然在跑,其實這已經算是內存泄露了。
如果內存會周期性地按時增長,泄露最終將導致瀏覽器變慢或者停止執行腳本。從性能優化角度來講已經是不得不做的事情了。是想如果循環執行的代碼中包含了一個大數組new Array(1000000).join('*'),那是非常危險的。
一般setTimeout遞歸是在做輪詢,這會需要給一個結束條件,執行clearTimeout。
Ⅶ 內存泄露監控腳本,怎麼寫
LR模擬大量user運行比較長的時間 監控待測伺服器的內存佔用 正常情況下應該是有申請有釋放 不構成泄漏 如果內存佔用一直在增加 沒有下降的區段 就是存在內存泄漏無疑了 斜率越大 泄漏越快
Ⅷ 嵌入式linux怎麼檢內存泄漏雨
1. 在需要內存泄漏檢查的代碼的開始調用void mtrace(void) (在mcheck.h中? 有聲明). mtrace為malloc等函數安裝hook, 用於記錄內存分配信息.在需要內存泄漏檢查的代碼的結束調用void muntrace(void).
注意: 一般情況下不要調用muntrace, 而讓程序自然結束. 因為可能有些釋放內存代碼要到muntrace之後才運行.
2. 用debug模式編譯被檢查代碼(-g或-ggdb)
3. 設置環境變數MALLOC_TRACE為一文件名, 這一文件將存有內存分配信息.
4. 運行被檢查程序, 直至結束或muntrace被調用.
5. 用mtrace命令解析內存分配Log文件($MALLOC_TRACE)
(mtrace foo $MALLOC_TRACE, where foo is the executible name)
如果有內存泄漏, mtrace會輸出分配泄漏
內存的代碼位置,以及分配數量.
附加說明
1. 可以將mtrace, muntrace放入信號處理函數(USR1, USR2), 以動態地進行內存泄漏檢查控制.
2. mtrace是個perl代碼, 如果你對符號地址與代碼文本的轉換感興趣, 可以讀一下.
3. again, 盡量不要用muntrace()
For C++ Leak:
檢查內存泄漏的方法除glibc提供外;還可以試試一些專用的程序。
很奇怪,redhat 9 居然不帶mtrace perl腳本,只好下載gcc源碼編譯了
wget --passive-ftp ftp://rpmfind.net/linux/redhat/9 ... -2.3.2-11.9.src.rpm
rpm -ivh glibc*.src.rpm
cd /usr/src/redhat/SPECS/
rpmbuild -ba glibc-9.spec
cd /var/tmp/glibc-2.3.2-root/usr/bin/
cp mtrace /usr/bin/
調試方法如下:
vi a.c
1 #include
2
3 int main()
4 {
5 mtrace();
6 malloc(10);
7 malloc(16);
8 return 0;
9 }
$gcc -g a.c #記得編譯帶-g調試選項
$export MALLOC_TRACE=a.log
$./a.out
$unset MALLOC_TRACE #記得執行完後unset變數,否則可能運行其他命令可能覆蓋log
$mtrace a.out a.log
Memory not freed:
-----------------
Address Size Caller
0x09b08378 0xa at /XXX/a.c:6
0x09b08388 0x10 at /XXX/a.c:7
可以看到,會顯示未釋放動態空間的代碼具體位置。
Ⅸ 如何使用JProfiler查找內存泄漏
先運行的java程序,然後打開jprofiler,綁定正在運行的程序,就可以在界面看到內存的使用情況。