內(nèi)存泄漏怎么判斷
你有沒(méi)有遇到過(guò)這種情況:電腦用著用著就變慢,任務(wù)管理器里某個(gè)程序的內(nèi)存占用一路飆升,關(guān)掉它才恢復(fù)正常?這很可能就是內(nèi)存泄漏在作怪。程序用了內(nèi)存卻沒(méi)及時(shí)還回去,像水龍頭漏水一樣,時(shí)間一長(zhǎng)系統(tǒng)就被拖垮。
觀察內(nèi)存使用趨勢(shì)
最直接的辦法是打開(kāi)系統(tǒng)自帶的資源監(jiān)視工具。Windows 上按 Ctrl+Shift+Esc 打開(kāi)任務(wù)管理器,切換到“性能”標(biāo)簽,選中“內(nèi)存”,持續(xù)觀察使用情況。如果某個(gè)程序運(yùn)行期間內(nèi)存占用不斷上升,即使操作已經(jīng)完成也不下降,那就有問(wèn)題了。
比如你在測(cè)試一個(gè)圖片處理工具,批量處理完100張圖后,內(nèi)存從500MB漲到2.3GB還不回落,這就很可疑。正常情況下處理完應(yīng)該釋放大部分內(nèi)存。
用專(zhuān)業(yè)工具抓細(xì)節(jié)
任務(wù)管理器只能看個(gè)大概,深入排查得靠更專(zhuān)業(yè)的工具。Windows 平臺(tái)可以用 Visual Studio 自帶的診斷工具,或者輕量級(jí)的 Process Explorer。Mac 和 Linux 用戶(hù)可以依賴(lài) Instruments 或 valgrind。
以 valgrind 為例,在終端運(yùn)行:
valgrind --tool=memcheck --leak-check=yes your_program它會(huì)詳細(xì)報(bào)告哪些代碼分配了內(nèi)存但沒(méi)有釋放,甚至能定位到具體行號(hào)。
代碼里埋點(diǎn)檢測(cè)
如果你是開(kāi)發(fā)者,可以在關(guān)鍵位置加日志。比如每次 malloc 分配內(nèi)存時(shí)記錄一次,free 時(shí)再記一次。運(yùn)行一段時(shí)間后對(duì)比數(shù)量是否匹配。不匹配就意味著有內(nèi)存沒(méi)被回收。
C++ 項(xiàng)目中也可以重載 new 和 delete 操作符,統(tǒng)計(jì)當(dāng)前未釋放的對(duì)象數(shù)量:
void* operator new(size_t size) {
void* ptr = malloc(size);
++allocation_count;
return ptr;
}
void operator delete(void* ptr) noexcept {
--allocation_count;
free(ptr);
}運(yùn)行過(guò)程中打印 allocation_count,看它是否會(huì)無(wú)限增長(zhǎng)。
瀏覽器里的內(nèi)存泄漏怎么看
網(wǎng)頁(yè)應(yīng)用也不能幸免。Chrome 開(kāi)發(fā)者工具的 Memory 面板就能派上用場(chǎng)。先刷新頁(yè)面記錄初始內(nèi)存,然后反復(fù)點(diǎn)擊某個(gè)功能按鈕,比如“添加商品到購(gòu)物車(chē)”。操作十幾次后再看內(nèi)存快照,如果堆內(nèi)存持續(xù)上漲且不回收,說(shuō)明可能有 DOM 節(jié)點(diǎn)或事件監(jiān)聽(tīng)沒(méi)清理。
記得有一次調(diào)試一個(gè)后臺(tái)管理系統(tǒng),用戶(hù)反饋切換菜單越來(lái)越卡。用 Chrome 抓了幾個(gè)快照對(duì)比,發(fā)現(xiàn)每次切換都會(huì)多出幾百個(gè)閉包和DOM引用,原來(lái)是事件綁定重復(fù)注冊(cè)了,改完之后內(nèi)存穩(wěn)住了。
別忽視第三方庫(kù)
有時(shí)候鍋不在自己寫(xiě)的代碼上。某些老舊的第三方組件可能存在內(nèi)存泄漏問(wèn)題。比如一個(gè)PDF預(yù)覽插件,在頁(yè)面關(guān)閉后仍持有大量數(shù)據(jù)引用。這時(shí)候就得靠隔離測(cè)試:逐個(gè)禁用外部腳本,觀察內(nèi)存變化趨勢(shì),縮小懷疑范圍。
內(nèi)存泄漏不一定立刻暴露,可能運(yùn)行幾小時(shí)才顯現(xiàn)。所以長(zhǎng)時(shí)間運(yùn)行的服務(wù)類(lèi)程序更要注意定期壓測(cè)和監(jiān)控。發(fā)現(xiàn)問(wèn)題越早,修復(fù)成本越低。