was修改堆記憶體 C語言記憶體洩露很嚴重,如何應對?

2021-10-14 12:54:15 字數 2381 閱讀 7216

摘要:通過介紹記憶體洩漏問題原理及檢視方法,希望後續能夠從編碼檢視環節就杜絕記憶體洩漏導致的網上問題發生。

最近部門不同產品接連出現記憶體洩漏導致的網上問題,具體表現為單板在現網執行數月以後,因為記憶體耗盡而導致單板復位現象。一方面,記憶體洩漏問題屬於低階錯誤,此類問題遺漏到現網,影響很壞;另一方面,由於記憶體洩漏問題很可能導致單板執行固定時間以後就復位,只能通過批量公升級才能解決,實際影響也很惡劣。同時,接連出現此類問題,尤其是其中一例問題還是我們老員工修改引入,說明我們不少員工對記憶體洩漏問題認識還是不夠深刻的。本文通過介紹記憶體洩漏問題原理及檢視方法,希望後續能夠從編碼檢視環節就杜絕此類問題發生。

記憶體洩漏問題只有在使用堆記憶體的時候才會出現,棧記憶體不存在記憶體洩漏問題,因為棧記憶體會自動分配和釋放。c**中堆記憶體的申請函式是malloc,常見的記憶體申請**如下:

char *info = null;    /**轉換後的字串**/    info = (char*)malloc(nb_mem_spd_info_max_size);    if( null == info)    複製**
由於malloc函式返回的實際上是乙個記憶體位址,所以儲存堆記憶體的變數一定是乙個指標(除非**編寫極其不規範)。再重複一遍,儲存堆記憶體的變數一定是乙個指標,這對本文主旨的理解很重要。當然,這個指標可以是單指標,也可以是多重指標。

malloc函式有很多變種或封裝,如g_malloc、g_malloc0、vos_malloc等,這些函式最終都會呼叫malloc函式。

看到本小節標題,可能有些同學有疑惑,上一小節中的malloc函式,不就是堆記憶體的獲取方法嗎?的確是,通過malloc函式申請是最直接的獲取方法,如果只知道這種堆記憶體獲取方法,就容易掉到坑里了。一般的來講,堆記憶體有如下兩種獲取方法:

方法一:將函式返回值直接賦給指標,一般表現形式如下:

char *local_pointer_xx = null;local_pointer_xx = (char*)function_xx(para_xx, …);複製**
該類涉及到記憶體申請的函式,返回值一般都指標型別,例如:

int ret;    char *local_pointer_xx = null;    /**轉換後的字串**/    ret = (char*)function_xx(..., &local_pointer_xx, ...);複製**
該類涉及到記憶體申請的函式,一般都有乙個入參是雙重指標,例如:

__stdio_inline _io_ssize_tgetline (char **__lineptr, size_t *__n, file *__stream)複製**
前面說通過malloc申請記憶體,就屬於方法一的乙個具體表現形式。其實這兩類方法的本質是一樣的,都是函式內部間接申請了記憶體,只是傳遞記憶體的方法不一樣,方法一通過返回值傳遞記憶體指標,方法二通過引數傳遞記憶體指標。

最常見的記憶體洩漏問題,包含以下三個要素:

要素一:函式內有區域性指標變數定義;

稍微使用過c語言編寫**的人,都應該知道堆記憶體申請之後是需要釋放的。但為何還這麼容易出現記憶體洩漏問題呢?一方面,是開發人員經驗不足、意識不到位或一時疏忽導致;另一方面,是記憶體釋放誤區導致。很多開發人員,認為要釋放的記憶體應該侷限於以下兩種:

1)直接使用記憶體申請函式申請出來的記憶體,如malloc、g_malloc等;

2)該開發人員熟悉的介面中,存在記憶體申請的情況,如ibmc的兄弟,都應該知道呼叫如下介面需要釋放list指向的記憶體:

dfl_get_object_list(const char* class_name, gslist **list)複製**
按照以上思維編寫**,一旦遇到不熟悉的介面中需要釋放記憶體的問題,就完全沒有釋放記憶體的意識,記憶體洩漏問題就自然產生了。

檢視記憶體洩漏問題,關鍵還是要養成良好的編碼檢視習慣。與記憶體洩漏三要素對應,需

要做到如下三點:

(1)在函式中看到有區域性指標,就要警惕記憶體洩漏問題,養成進一步排查的習慣

(2)分析對區域性指標的賦值操作,是否屬於前面所說的「兩種堆記憶體獲取方法」之一,如果是,就要分析函式返回的指標到底指向啥?是全域性資料、靜態資料還是堆記憶體?對於不熟悉的介面,要找到對應的介面文件或源**分析;又或者看看**中其它地方對該介面的引用,是否進行了記憶體釋放;

(3)如果確認對區域性指標存在記憶體申請操作,就需要分析該記憶體的去向,是會被儲存在全域性變數嗎?又或者會被作為函式返回值嗎?如果都不是,就需要排查函式所有有」return「的地方,保證記憶體被正確釋放。

C 堆記憶體空間詳解 釋放記憶體 記憶體洩露

家裡要來客人了,我們要給客人們泡茶。如果規定只能在確定來幾位客人之前就把茶泡好,這就會顯得很尷尬 茶泡多了會造成浪費,泡少了怕怠慢了客人。所以,最好的方法就是等知道了來幾位客人再泡茶,來幾位客人就泡幾杯茶。然而,我們在使用陣列的時候也會面臨這種尷尬 陣列的儲存空間必須在程式執行前申請,即陣列的大小在...

C 堆記憶體空間詳解 釋放記憶體 記憶體洩露

家裡要來客人了,我們要給客人們泡茶。如果規定只能在確定來幾位客人之前就把茶泡好,這就會顯得很尷尬 茶泡多了會造成浪費,泡少了怕怠慢了客人。所以,最好的方法就是等知道了來幾位客人再泡茶,來幾位客人就泡幾杯茶。然而,我們在使用陣列的時候也會面臨這種尷尬 陣列的儲存空間必須在程式執行前申請,即陣列的大小在...

C 記憶體洩露

簡單點說就是只申請不釋放 在c 中我們通過malloc,new來通過系統申請記憶體,但當我們使用完畢之後 裡面可能就沒有執行相應的free和delete的操作,這樣我們申請的這部分記憶體系統就不會再次的 分配,這就造成了記憶體洩露!這篇帖子講的很細大家可以研究研究。我們在delete乙個指標之後要將...