可能不少開發(fā)者都遇到過(guò)內(nèi)存泄漏導(dǎo)致的網(wǎng)上問(wèn)題,具體表現(xiàn)為單板在現(xiàn)網(wǎng)運(yùn)行數(shù)月以后,因?yàn)閮?nèi)存耗盡而導(dǎo)致單板復(fù)位現(xiàn)象。一方面,內(nèi)存泄漏問(wèn)題屬于比較淺顯的錯(cuò)誤,此類問(wèn)題遺漏到現(xiàn)網(wǎng),影響不好;另一方面,由于內(nèi)存泄漏問(wèn)題很可能導(dǎo)致單板運(yùn)行固定時(shí)間以后就復(fù)位,只能通過(guò)批量升級(jí)才能解決,實(shí)際影響不佳。本文通過(guò)介紹內(nèi)存泄漏問(wèn)題原理及檢視方法,希望后續(xù)能夠從編碼檢視環(huán)節(jié)就杜絕此類問(wèn)題發(fā)生。
說(shuō)明:預(yù)防內(nèi)存泄漏問(wèn)題有多種方法,如加強(qiáng)代碼檢視、工具檢測(cè)和內(nèi)存測(cè)試等,本文聚集于開發(fā)人員能力提升方面。
01
內(nèi)存泄漏問(wèn)題原理
堆內(nèi)存在C代碼中的存儲(chǔ)方式
內(nèi)存泄漏問(wèn)題只有在使用堆內(nèi)存的時(shí)候才會(huì)出現(xiàn),棧內(nèi)存不存在內(nèi)存泄漏問(wèn)題,因?yàn)闂?nèi)存會(huì)自動(dòng)分配和釋放。C代碼中堆內(nèi)存的申請(qǐng)函數(shù)是malloc,常見的內(nèi)存申請(qǐng)代碼如下:
char *info = NULL; /**轉(zhuǎn)換后的字符串**/ info = (char*)malloc(NB_MEM_SPD_INFO_MAX_SIZE); if( NULL == info) { (void)tdm_error("malloc error! "); return NB_SA_ERR_HPI_OUT_OF_MEMORY; }
由于malloc函數(shù)返回的實(shí)際上是一個(gè)內(nèi)存地址,所以保存堆內(nèi)存的變量一定是一個(gè)指針(除非代碼編寫極其不規(guī)范)。再重復(fù)一遍,保存堆內(nèi)存的變量一定是一個(gè)指針,這對(duì)本文主旨的理解很重要。當(dāng)然,這個(gè)指針可以是單指針,也可以是多重指針。 malloc函數(shù)有很多變種或封裝,如g_malloc、g_malloc0、VOS_Malloc等,這些函數(shù)最終都會(huì)調(diào)用malloc函數(shù)。
堆內(nèi)存的獲取方法
看到本小節(jié)標(biāo)題,可能有些同學(xué)有疑惑,上一小節(jié)中的malloc函數(shù),不就是堆內(nèi)存的獲取方法嗎?的確是,通過(guò)malloc函數(shù)申請(qǐng)是最直接的獲取方法,如果只知道這種堆內(nèi)存獲取方法,就容易掉到坑里了。一般的來(lái)講,堆內(nèi)存有如下兩種獲取方法: 方法一:將函數(shù)返回值直接賦給指針,一般表現(xiàn)形式如下:
char *local_pointer_xx = NULL;local_pointer_xx = (char*)function_xx(para_xx, …);
該類涉及到內(nèi)存申請(qǐng)的函數(shù),返回值一般都指針類型,例如:
GSList* g_slist_append (GSList *list, gpointer data)
方法二:將指針地址作為函數(shù)返回參數(shù),通過(guò)返回參數(shù)保存堆內(nèi)存地址,一般表現(xiàn)形式如下:
int ret; char *local_pointer_xx = NULL; /**轉(zhuǎn)換后的字符串**/ ret = (char*)function_xx(..., &local_pointer_xx, ...);
該類涉及到內(nèi)存申請(qǐng)的函數(shù),一般都有一個(gè)入?yún)⑹请p重指針,例如:
__STDIO_INLINE _IO_ssize_tgetline (char **__lineptr, size_t *__n, FILE *__stream)
前面說(shuō)通過(guò)malloc申請(qǐng)內(nèi)存,就屬于方法一的一個(gè)具體表現(xiàn)形式。其實(shí)這兩類方法的本質(zhì)是一樣的,都是函數(shù)內(nèi)部間接申請(qǐng)了內(nèi)存,只是傳遞內(nèi)存的方法不一樣,方法一通過(guò)返回值傳遞內(nèi)存指針,方法二通過(guò)參數(shù)傳遞內(nèi)存指針。
內(nèi)存泄漏三要素
最常見的內(nèi)存泄漏問(wèn)題,包含以下三個(gè)要素:
要素一:函數(shù)內(nèi)有局部指針變量定義;
要素二:對(duì)該局部指針有通過(guò)上一小節(jié)中“兩種堆內(nèi)存獲取方法”之一獲取內(nèi)存;
要素三:在函數(shù)返回前(含正常分支和異常分支)未釋放該內(nèi)存,也未保存到其它全局變量或返回給上一級(jí)函數(shù)。
內(nèi)存釋放誤區(qū)
稍微使用過(guò)C語(yǔ)言編寫代碼的人,都應(yīng)該知道堆內(nèi)存申請(qǐng)之后是需要釋放的。但為何還這么容易出現(xiàn)內(nèi)存泄漏問(wèn)題呢?一方面,是開發(fā)人員經(jīng)驗(yàn)不足、意識(shí)不到位或一時(shí)疏忽導(dǎo)致;另一方面,是內(nèi)存釋放誤區(qū)導(dǎo)致。很多開發(fā)人員,認(rèn)為要釋放的內(nèi)存應(yīng)該局限于以下兩種:
(1)直接使用內(nèi)存申請(qǐng)函數(shù)申請(qǐng)出來(lái)的內(nèi)存,如malloc、g_malloc等; (2)該開發(fā)人員熟悉的接口中,存在內(nèi)存申請(qǐng)的情況,如iBMC的兄弟,都應(yīng)該知道調(diào)用如下接口需要釋放list指向的內(nèi)存:
dfl_get_object_list(const char* class_name, GSList **list) 按照以上思維編寫代碼,一旦遇到不熟悉的接口中需要釋放內(nèi)存的問(wèn)題,就完全沒有釋放內(nèi)存的意識(shí),內(nèi)存泄漏問(wèn)題就自然產(chǎn)生了。
02
內(nèi)存泄漏問(wèn)題檢視方法
檢視內(nèi)存泄漏問(wèn)題,關(guān)鍵還是要養(yǎng)成良好的編碼檢視習(xí)慣。與內(nèi)存泄漏三要素對(duì)應(yīng),需要做到如下三點(diǎn):
(1)在函數(shù)中看到有局部指針,就要警惕內(nèi)存泄漏問(wèn)題,養(yǎng)成進(jìn)一步排查的習(xí)慣;
(2)分析對(duì)局部指針的賦值操作,是否屬于前面所說(shuō)的“兩種堆內(nèi)存獲取方法”之一,如果是,就要分析函數(shù)返回的指針到底指向啥?是全局?jǐn)?shù)據(jù)、靜態(tài)數(shù)據(jù)還是堆內(nèi)存?對(duì)于不熟悉的接口,要找到對(duì)應(yīng)的接口文檔或源代碼分析;又或者看看代碼中其它地方對(duì)該接口的引用,是否進(jìn)行了內(nèi)存釋放; (3)如果確認(rèn)對(duì)局部指針存在內(nèi)存申請(qǐng)操作,就需要分析該內(nèi)存的去向,是會(huì)被保存在全局變量嗎?又或者會(huì)被作為函數(shù)返回值嗎?如果都不是,就需要排查函數(shù)所有有”return“的地方,保證內(nèi)存被正確釋放。
責(zé)任編輯:YYX
-
內(nèi)存
+關(guān)注
關(guān)注
9文章
3209瀏覽量
76357 -
C代碼
+關(guān)注
關(guān)注
1文章
90瀏覽量
15182
原文標(biāo)題:從原理到方法,一文講清如何應(yīng)對(duì)C語(yǔ)言內(nèi)存泄露!
文章出處:【微信號(hào):Huawei_Developer,微信公眾號(hào):華為開發(fā)者社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
儲(chǔ)能安全警報(bào):冷卻液泄漏的隱患與檢測(cè)難題 | 星科創(chuàng)科技解讀
內(nèi)存持續(xù)漲價(jià),多重信號(hào)預(yù)警成本壓力#內(nèi)存芯片#漲價(jià)#行業(yè)#消費(fèi)電子#AI#
化工廠液體泄漏識(shí)別預(yù)警系統(tǒng)
WebGL/Canvas 內(nèi)存泄露分析
at_device 包 ml307長(zhǎng)時(shí)間運(yùn)行有內(nèi)存泄漏問(wèn)題怎么解決?
產(chǎn)品密封性防水泄漏標(biāo)準(zhǔn)如何判定?精誠(chéng)工科氣密性檢測(cè)儀的設(shè)置方法
在OpenVINO? C++代碼中啟用 AddressSanitizer 時(shí)的內(nèi)存泄漏怎么解決?
鴻蒙5開發(fā)寶藏案例分享---內(nèi)存優(yōu)化實(shí)戰(zhàn)指南
HarmonyOS優(yōu)化應(yīng)用內(nèi)存占用問(wèn)題性能優(yōu)化一
快問(wèn)快答:泄漏等級(jí)有哪些?含閥門氣密性檢測(cè)原理方法和解決方案
傳統(tǒng)檢測(cè)方法VS電子芯片氣密性檢測(cè)儀,差距一目了然
推薦兩款菲力爾氣體泄漏檢測(cè)神器
快速搞懂C語(yǔ)言程序內(nèi)存分區(qū)!
內(nèi)存泄漏問(wèn)題原理及檢視方法
評(píng)論