HarmonyOS開發(fā)中限嫌,高效定位分析內(nèi)存異常問題的四種方案

應用在開發(fā)過程中,可能會因為API使用錯誤时捌、變量未及時釋放怒医、異常頻繁創(chuàng)建/釋放內(nèi)存等情況引發(fā)各種內(nèi)存問題。

華為官方提供了多種方案來方便各位開發(fā)者分析解決內(nèi)存相關(guān)問題奢讨,比如Allocation (獲取native調(diào)用棧profiler)稚叹、SnapShot、ASan拿诸、HWASan扒袖,本文重點對這些工具的特點做些說明,同時結(jié)合實際案例對這些工具的應用做進一步講解亩码。

(1)Allocation的應用

Allocation是DevEco Studio 開發(fā)工具的 Profiler提供的內(nèi)存場景分析工具季率,開發(fā)過程中可以使用Allocation來分析應用或服務在運行時的內(nèi)存分配及使用情況,識別和定位內(nèi)存泄漏蟀伸、內(nèi)存抖動以及內(nèi)存溢出等問題蚀同,對應用或服務的內(nèi)存使用進行優(yōu)化。

調(diào)試方式

打開 DevEco Studio 找到 Profiler啊掏,DevEco Profiler提供Launch蠢络、ArkUI、Frame迟蜜、Concurrency刹孔、ArkWeb、Network、Time髓霞、Allocation卦睹、Snapshot、CPU等場景化分析任務類型方库,在設備列表中選擇設備(目前只支持真機)结序,在進程列表中選擇要調(diào)測的應用,選擇Allocation并點擊Create Session即可創(chuàng)建一次會話纵潦。右側(cè)任務分析窗口可以選擇Memory徐鹤、Native Allocation具體分析。

image.png

Memory泳道

可以看到Memory泳道包含三個標識:PSS代表進程獨占內(nèi)存和按比例分配共享庫占用內(nèi)存之和邀层,RSS是進程獨占內(nèi)存和相關(guān)共享庫占用內(nèi)存之和返敬,USS代表進程獨占內(nèi)存。

在右邊錄制詳情區(qū)域寥院,工具控制欄上有很多小圖標劲赠,鼠標放上去會有一些功能提示,可以添加一些錄制選項秸谢,各泳道區(qū)域也有下拉框選項凛澎,下拉選擇不同的設置可以調(diào)整錄制功能。

單擊任務窗口左上角的 钮追,啟動錄制预厌,也可以選擇左側(cè)的任務列表中的阿迈,啟動錄制后元媚,等待任務狀態(tài)由“initializing”變?yōu)椤皉ecording”。錄制過程中整個DevEco Profiler不能再點擊其他的模板進行操作苗沧,如果想錄制其他模板可以結(jié)束本次錄制重新選擇其他模板開始錄制刊棕。

image.png

錄制過程中,右側(cè)任務分析窗口顯示未recording狀態(tài)待逞,先要結(jié)束此次錄制時甥角,點擊左側(cè)Allocation按鈕的stop按鈕即可,結(jié)束錄制之后可以看到當前session的各個不同內(nèi)存類型對應的變化情況识樱。

默認展示其中的五個子泳道嗤无,如要顯示其他子泳道,可以點擊主泳道的options標簽并勾選其他泳道來查看怜庸。

image.png

選擇具體的子泳道可以在details模塊看到不同的時間點当犯,對應的內(nèi)存值變化情況,方便開發(fā)者進一步定位問題割疾。

image.png

特別提示:

● 由于隱私安全政策嚎卫,已上架應用市場的應用不支持錄制此泳道。

● 建議避免同時錄制ArkTS Allocation及Native Allocation泳道宏榕,避免影響分析準確性拓诸。

Native Allocation泳道

Native Allocation泳道主要顯示具體的Native內(nèi)存分配情況侵佃,包括靜態(tài)統(tǒng)計數(shù)據(jù)、分配棧、每層函數(shù)棧消耗的Native內(nèi)存等信息抽活。由于隱私安全政策墩新,已上架應用市場的應用不支持錄制此泳道。通過操作對應的options同樣可以選擇展示的類型首有,框選子泳道后顯示具體的內(nèi)存分配,包括靜態(tài)統(tǒng)計數(shù)據(jù)枢劝、分配棧等井联。

image.png

如下圖所示,為選中Native Allocation后的某種展示場景您旁。

● Statistics顯示該段時間內(nèi)的靜態(tài)分配情況烙常。包括分配方式(Malloc或Mmap)、總分配內(nèi)存大小鹤盒、總分配次數(shù)蚕脏、尚未釋放的內(nèi)存大小、尚未釋放次數(shù)侦锯、已釋放的內(nèi)存大小驼鞭、已釋放次數(shù)。

點擊任意對象上的跳轉(zhuǎn)按鈕尺碰,可跳轉(zhuǎn)至此類對象的詳細占用/分配信息挣棕。當前統(tǒng)計模式下不支持跳轉(zhuǎn)。

● Call Trees頁簽顯示線程的內(nèi)存分配棧情況亲桥。包括函數(shù)地址或符號洛心、分配大小、占比以及函數(shù)棧幀的類別等题篷。單擊任一行棧幀词身,“More”區(qū)域?qū)@示經(jīng)過該棧幀的分配內(nèi)存最大的調(diào)用棧。

● Allocations List顯示內(nèi)存分配的詳細信息番枚。包括內(nèi)存塊起始地址法严、時間戳、當前活動狀態(tài)葫笼、大小深啤、調(diào)用的庫、調(diào)用庫的具體函數(shù)渔欢、事件類型(與Statistics頁簽的分配方式對應)等墓塌。

針對詳情面板中所展示的函數(shù)棧幀信息(如下圖所示),雙擊棧幀結(jié)點,工具便會在編輯器中打開相關(guān)源碼文件苫幢,并定位到對應行號访诱。此功能正常使用的前提是用于抓取性能數(shù)據(jù)的應用,是在DevEco Studio所在的開發(fā)環(huán)境中編譯韩肝,且相關(guān)源文件位置并未改變触菜。

image.png

值得注意的是,上圖對應的category列表標識調(diào)用棧的類型哀峻,從語言層面分為ArkTS涡相、NAPI以及Native,從歸屬層面分為開發(fā)者代碼以及系統(tǒng)代碼(如下圖所示)剩蟀。從這兩個方面可以將調(diào)用棧類型歸類如下:

ArkTS:程序正在執(zhí)行ArkTS代碼催蝗;

NAPI:程序正在運行的NAPI代碼;

Native:程序正在執(zhí)行的Native代碼育特;其中每一個類型的亮色和灰色分別代表開發(fā)者和系統(tǒng)的代碼丙号。

image.jpeg

Native Allocation泳道的內(nèi)存狀態(tài)信息可以進一步過濾和篩選。選中Native Allocation后缰冤,details底部有兩個默認過濾條件All Allocations犬缨、Native Size。

● All Allocations(默認狀態(tài)):詳情區(qū)域展示當前框選時間段內(nèi)的所有內(nèi)存分配信息

● Created & Existing:詳情區(qū)域展示當前框選時間段內(nèi)分配未釋放的內(nèi)存棉浸。

● Created & Released:詳情區(qū)域展示當前框選時間段內(nèi)分配已釋放的內(nèi)存怀薛。

image.png

Native Size:詳情區(qū)域按照對象的原生內(nèi)存進行展示。

● Native Library:詳情區(qū)域按照對象的so庫進行展示迷郑。

image.png

此外枝恋,在“Native Allocation”泳道的“Allocations List”頁簽中還可以通過so庫名稱進行篩選、搜索關(guān)鍵詞篩選三热、內(nèi)存分配堆棧進行篩選鼓择,此處不再做過多演示。

關(guān)于Allocation的更多介紹和使用方法可以在官方文檔查看就漾,基礎(chǔ)內(nèi)存之Allocation分析

(2)Snapshot

Snapshot是DevEco Profiler提供的一個內(nèi)存快照分析工具念搬,通過結(jié)合Memory實時占用情況抑堡,分析不同時刻的方舟虛擬機內(nèi)存對象占用情況及差異,進而進行內(nèi)存優(yōu)化朗徊。

關(guān)于Snapshot具體的應用技巧可以借鑒官網(wǎng)Snapshot模板基本操作首妖,或者借鑒使用Snapshot Insight分析ArkTS內(nèi)存問題,本文不再贅述爷恳。

(3)ASan的應用

ASan(Address-Sanitizer)是內(nèi)存檢測的工具有缆,用于發(fā)現(xiàn)內(nèi)存飛踩第一現(xiàn)場,DevEco Studio為開發(fā)者集成了ASan能力,可以檢測C/C++的地址越界問題棚壁,解決一些踩內(nèi)存導致的異常crash的補充手段杯矩,對于一些明顯不可能crash的場景可以嘗試開啟ASan。

使用約束

● 如果應用內(nèi)的任一模塊使能ASan袖外,那么entry模塊需同時使能ASan史隆。

● 如果entry模塊未使能ASan,該應用在啟動時將閃退曼验,出現(xiàn)CPP Crash報錯泌射。

● ASan、TSan鬓照、HWASan不能同時開啟熔酷,三個只能開啟其中一個。

配置參數(shù)

ASAN_OPTIONS:在運行時配置ASan的行為豺裆,包括設置檢測級別纯陨、輸出格式、內(nèi)存錯誤報告的詳細程度等留储。ASAN_OPTIONS支持在app.json5中配置翼抠,也支持在Run/Debug Configurations中配置。app.json5的優(yōu)先級較高获讳,即兩種方式都配置后阴颖,以app.json5中的配置為準。

以在app.json5中配置環(huán)境變量為例丐膝。打開AppScope > app.json5文件量愧,添加配置示例如下。

{  "app": {    "appEnvironments": [      {        "name": "ASAN_OPTIONS",        "value": "log_exe_name=true abort_on_error=0 print_cmdline=true" // 示例僅供參考帅矗,具體以實際為準      },    ],    ...  }}

在Run/Debug Configurations中配置環(huán)境變量偎肃,具體可查看配置環(huán)境變量

使能ASan

可通過以下兩種方式使能ASan浑此。

方式一

1. 在運行調(diào)試窗口(entry --> Edit Configurations)累颂,點擊Diagnostics,勾選Address Sanitizer凛俱。

image.png
image.png

2. 如果有引用本地library紊馏,需在library模塊的build-profile.json5文件中,配置arguments字段值為“-DOHOS_ENABLE_ASAN=ON”蒲犬,表示以ASan模式編譯so文件朱监。

image.png

方式二

1. 修改工程目錄下AppScope/app.json5,添加ASan配置開關(guān)原叮。

 "asanEnabled": true
image.png

2. 設置模塊級構(gòu)建ASan插樁赫编。

在需要使能ASan的模塊中巡蘸,通過添加構(gòu)建參數(shù)開啟ASan檢測插樁,在對應模塊的模塊級build-profile.json5中添加命令參數(shù):

"arguments": "-DOHOS_ENABLE_ASAN=ON"
image.png

啟用ASan

運行或調(diào)試當前應用擂送。

當程序出現(xiàn)內(nèi)存錯誤時悦荒,彈出ASan log信息,點擊信息中的鏈接即可跳轉(zhuǎn)至引起內(nèi)存錯誤的代碼處团甲。

舉例說明:

編寫一段數(shù)組越界的C++代碼逾冬,對外暴露接口,在ArkTs側(cè)調(diào)用該方法躺苦。

image.png
Text(this.message)          .fontSize(50)          .fontWeight(FontWeight.Bold)          .onClick(() => {            hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3));            hilog.info(0x0000, 'testTag', 'HeapBufferOverflow() ', testNapi.HeapBufferOverflow());            // this.memoryLeak()          })

運行當前項目身腻,觸發(fā)Button的onClick事件調(diào)用之后,應用崩潰匹厘,彈出FaultLog信息嘀趟。

image.png

點擊 Jump to Log跳轉(zhuǎn)到FaultLog模塊。

image.png

可以看到log信息有明確的log信息愈诚,報錯原因為“AddressSanitizer: heap-buffer-overflow”她按,同樣還有多個鏈接地址】蝗幔“==appspawn==30149==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x005b7fe7153b at pc 0x007c24fc309c bp 0x007eba84b160 sp 0x007eba84b158

”可以直接跳轉(zhuǎn)到官網(wǎng)關(guān)于“heap-buffer-overflow”的報錯解釋以及解決方案酌泰。另外多個包含“/data/storage/el1/...”的地址能精確定位到C/C++層代碼出錯的具體位置。

image.png

然后我們就發(fā)現(xiàn)這是數(shù)組越界造成的匕累,所以解決方案就是“對于已知大小的集合陵刹,注意訪問不要越界,位置大小的集合訪問前先判斷大小欢嘿∷ニ觯”

ASan檢測異常碼

ASan不僅能檢測出“heap-buffer-overflow”異常,還能檢測很多其他類型的內(nèi)存異常炼蹦,關(guān)于這些異常問題及解決方案羡宙,如下所示。

● heap-buffer-overflow

● 背景/原理:訪問越界掐隐。

● 影響/報錯:導致程序存在安全漏洞狗热,并有崩潰風險。

開啟ASan檢測后瑟枫,觸發(fā)demo中的函數(shù),應用閃退報ASan慷妙,包含字段:AddressSanitizer:heap-buffer-overflow

● 修改方法:注意數(shù)組容量不要訪問越界。

● 推薦建議:已知大小的集合注意訪問不要越界允悦,位置大小的集合訪問前先判斷大小膝擂。

● stack-buffer-underflow

● 背景/原理:訪問越下界虑啤。

● 影響/報錯:導致程序存在安全漏洞,并有崩潰風險架馋。

開啟ASan檢測后狞山,觸發(fā)demo中的函數(shù),應用閃退報ASan叉寂,包含字段:AddressSanitizer:stack-buffer-underflow

● 修改方法:訪問索引不應小于下界萍启。

● 推薦建議:訪問索引不應小于下界。

● stack-use-after-scope

● 背景/原理:棧變量在作用域之外被使用屏鳍。

● 影響/報錯:導致程序存在安全漏洞勘纯,并有崩潰風險。

開啟ASan檢測后钓瞭,觸發(fā)demo中的函數(shù)驳遵,應用閃退報ASan,包含字段:AddressSanitizer:stack-use-after-scope

● 修改方法:在作用域內(nèi)使用該變量山涡。

● 推薦建議:注意變量作用域堤结。

● attempt-free-nonallocated-memory

● 背景/原理:嘗試釋放了非堆對象(non-heap object)或未分配內(nèi)存。

● 影響/報錯:導致程序存在安全漏洞鸭丛,并有崩潰風險竞穷。

開啟ASan檢測后,觸發(fā)demo中的函數(shù)鳞溉,應用閃退報ASan瘾带,包含字段:

AddressSanitizer: attempting free on address which was not malloc()-ed

● 修改方法:不要對非堆對象或未分配的內(nèi)存使用free函數(shù)。

● 推薦建議:不要對非堆對象或未分配的內(nèi)存使用free函數(shù)穿挨。

● double-free

● 背景/原理:重復釋放內(nèi)存月弛。

● 影響/報錯:導致程序存在安全漏洞,并有崩潰風險科盛。

開啟ASan檢測后帽衙,觸發(fā)demo中的函數(shù),應用閃退報ASan贞绵,包含字段:

AddressSanitizer: double-free

● 修改方法:已經(jīng)釋放一次的指針厉萝,不要再重復釋放。

● 推薦建議:變量定義聲明時初始化為NULL榨崩,釋放內(nèi)存后也應立即將變量重置為NULL谴垫,這樣每次釋放之前都可以通過判斷變量是否為NULL來判斷是否可以釋放。

● heap-use-after-free

● 背景/原理:當指針指向的內(nèi)存被釋放后母蛛,仍然通過該指針訪問已經(jīng)被釋放的內(nèi)存翩剪,就會觸發(fā)heap-use-after-free。

● 影響/報錯:導致程序存在安全漏洞彩郊,并有崩潰風險前弯。

開啟ASan檢測后蚪缀,觸發(fā)demo中的函數(shù),應用閃退報ASan恕出,包含字段:

AddressSanitizer: heap-use-after-free

● 修改方法:已經(jīng)釋放的指針不要再使用询枚,將指針設置為NULL/nullptr。

● 推薦建議:實現(xiàn)一個free()的替代版本或者 delete析構(gòu)器來保證指針的重置浙巫。

● Other categories

未知的錯誤類型金蜀,持續(xù)更新中。

(4)HWASan的應用

HWASan(Hardware-Assisted Address Sanitizer)是一款類似于ASan的內(nèi)存錯誤檢測工具的畴,目前僅適用于渊抄。 與ASan相比,HWASan使用的內(nèi)存減少很多苗傅,因而更適合用于整個系統(tǒng)的清理抒线。

功能介紹

與ASan相比,HWASan具有如下特征:

● CPU開銷約為2倍渣慕。

● 代碼大小開銷為40% - 50%嘶炭。

● RAM開銷為10% - 35%。

HWASan能檢測到ASan所能檢測到的同一系列錯誤:

● 堆棧和堆緩沖區(qū)上溢/下溢逊桦。

● 釋放之后的堆使用情況眨猎。

● 重復釋放/錯誤釋放。

和ASan相比强经,HWASan具有以下優(yōu)點:

● HWASan不需要安全區(qū)來檢測buffer overflow睡陪,既極大地降低了工具對于內(nèi)存的消耗,也不會出現(xiàn)ASan中某些overflow檢測不到的情況匿情。

● HWASan不需要隔離區(qū)來檢測UseAfterFree兰迫,因此不會出現(xiàn)ASan中某些UseAfterFree檢測不到的情況。

● 此外炬称,HWASan還可以檢測返回之后的堆棧使用情況汁果。

約束條件

● HWASan檢測僅適用于AArch64架構(gòu)的硬件。

● ASan玲躯、TSan据德、HWASan不能同時開啟,三個只能開啟其中一個跷车。

使能HWASan

方式一

在運行調(diào)試窗口(例如entry --> Edit Configurations)棘利,點擊Diagnostics,勾選Hardware-Assisted Address Sanitizer開啟檢測朽缴。

image.png

方式二

修改工程目錄下的AppScope/app.json5文件善玫,添加HWASan配置開關(guān)。

"hwasanEnabled": true
image.png

在需要使能HWASan的模塊中密强,通過添加構(gòu)建參數(shù)開啟HWASan檢測插樁裹唆,在對應模塊的模塊級build-profile.json5中添加命令參數(shù):

"arguments": "-DOHOS_ENABLE_HWASAN=ON"
image.png

啟用HWASan

運行或調(diào)試當前應用只洒。當程序出現(xiàn)內(nèi)存錯誤時劳坑,彈出HWASan log信息,點擊信息中的鏈接即可跳轉(zhuǎn)至引起內(nèi)存錯誤的代碼處涝开。

關(guān)于HWAan的代碼實例和應用場景基本和ASan一致框仔,此處就不做重復是說明了。

總結(jié)

● 根據(jù)Allocation分析的結(jié)果银舱,可以方便開發(fā)者優(yōu)化應用的服務和組件的內(nèi)存使用跛梗。例如,減少不必要的內(nèi)存分配和釋放核偿,優(yōu)化數(shù)據(jù)結(jié)構(gòu)的使用等。

● 通過ASan或HWASan分析問題時轰绵,精準定位內(nèi)存出錯原因和具體位置尼荆,開發(fā)者應修復這些內(nèi)存管理的問題,如確保所有分配的內(nèi)存都被正確釋放翔悠。

● 開發(fā)過程中野芒,使用合適的內(nèi)存管理和回收機制 :確保應用在不需要內(nèi)存資源時能夠有效地回收和管理這些資源蓄愁,避免過度使用內(nèi)存狞悲。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市丹拯,隨后出現(xiàn)的幾起案子站超,更是在濱河造成了極大的恐慌乖酬,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件算撮,死亡現(xiàn)場離奇詭異县昂,居然都是意外死亡肮柜,警方通過查閱死者的電腦和手機审洞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門待讳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耙箍,“玉大人,你說我怎么就攤上這事阅酪≈耄” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵辉词,是天一觀的道長猾骡。 經(jīng)常有香客問我兴想,道長幢哨,這世上最難降的妖魔是什么嫂便? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上岸售,老公的妹妹穿的比我還像新娘践樱。我一直安慰自己,他們只是感情好拷邢,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著甲雅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪抛人。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天脐瑰,我揣著相機與錄音,去河邊找鬼苍在。 笑死绝页,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的寂恬。 我是一名探鬼主播续誉,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼初肉,長吁一口氣:“原來是場噩夢啊……” “哼酷鸦!你這毒婦竟也來了牙咏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤摔握,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后伊磺,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盛正,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡蛮艰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了壤蚜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片即寡。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖袜刷,靈堂內(nèi)的尸體忽然破棺而出聪富,到底是詐尸還是另有隱情,我是刑警寧澤著蟹,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布墩蔓,位于F島的核電站,受9級特大地震影響萧豆,放射性物質(zhì)發(fā)生泄漏奸披。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一涮雷、第九天 我趴在偏房一處隱蔽的房頂上張望阵面。 院中可真熱鬧,春花似錦洪鸭、人聲如沸样刷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽置鼻。三九已至,卻和暖如春蜓竹,著一層夾襖步出監(jiān)牢的瞬間箕母,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工梅肤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留司蔬,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓姨蝴,卻偏偏與公主長得像俊啼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子左医,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容