成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何通過wrap malloc定位C/C++程序的內存泄漏

開發 后端
用C/C++開發的程序執行效率很高,但卻經常受到內存泄漏的困擾。本文提供一種通過wrap malloc查找memory leak的思路。

用C/C++開發的程序執行效率很高,但卻經常受到內存泄漏的困擾。本文提供一種通過wrap malloc查找memory leak的思路。

[[278147]]

什么是內存泄漏?

動態申請的內存丟失引用,造成沒有辦法回收它(我知道杠jing要說進程退出前系統會統一回收),這便是內存泄漏。

Java等編程語言會自動管理內存回收,而C/C++需要顯式的釋放,有很多手段可以避免內存泄漏,比如RAII,比如智能指針(大多基于引用計數計數),比如內存池。

理論上,只要我們足夠小心,在每次申請的時候,都牢記釋放,那這個世界就清凈了,但現實往往沒有那么美好,比如拋異常了,釋放內存的語句執行不到,又或者某菜鳥程序員不小心埋了一個雷,所以,我們必須直面真實的世界,那就是我們會遭遇內存泄漏。

怎么查內存泄漏?

我們可以review代碼,但從海量代碼里找到隱藏的問題,這如同大海撈針,往往兩手空空。

所以,我們需要借助工具,比如valgrind,但這些找內存泄漏的工具,往往對你使用動態內存的方式有某種期待,或者說約束,比如常駐內存的對象會被誤報出來,然后真正有用的信息會掩蓋在誤報的汪洋大海里。很多時候,甚至valgrind根本解決不了日常項目中的問題。

所以很多著名的開源項目,為了能用valgrind跑,都費大力氣,大幅修改源代碼,從而使得項目符合valgrind的要求,滿足這些要求,用vargrind跑完沒有任何報警的項目叫valgrind干凈。

既然這些玩意兒都中看不中用,所以,求人不如求己,還是得自力更生。

什么是動態內存分配器?

動態內存分配器是介于kernel跟應用程序之間的一個函數庫,glibc提供的動態內存分配器叫ptmalloc,它也是應用最廣泛的動態內存分配器實現。

從kernel角度看,動態內存分配器屬于應用程序層;而從應用程序的角度看,動態內存分配器屬于系統層。

應用程序可以通過mmap系統直接向kernel申請動態內存,也可以通過動態內存分配器的malloc接口分配內存,而動態內存分配器會通過sbrk、mmap向kernel分配內存,所以應用程序通過free釋放的內存,并不一定會真正返還給系統,它也有可能被動態內存分配器緩存起來。

google有自己的動態內存分配器tcmalloc,另外jemalloc也是著名的動態內存分配器,他們有不同的性能表現,也有不同的緩存和分配策略。你可以用它們替換linux系統glibc自帶的ptmalloc。

new/delete跟malloc/free的關系

new是c++的用法,比如Foo *f = new Foo,其實它分為3步。

  • 通過operator new()分配sizeof(Foo)的內存,最終通過malloc分配。
  • 在新分配的內存上構建Foo對象。
  • 返回新構建的對象地址。

new=分配內存+構造+返回,而delete則是等于析構+free。

所以搞定malloc、free就是從根本上搞定動態內存分配。

1. chunk

每次通過malloc返回的一塊內存叫一個chunk,動態內存分配器是這樣定義的,后面我們都這樣稱呼。

2. wrap malloc

gcc支持wrap,即通過傳遞-Wl,--wrap,malloc的方式,可以改變調用malloc的行為,把對malloc的調用鏈接到自定義的__wrap_malloc(size_t)函數,而我們可以在__wrap_malloc(size_t)函數的實現中通過__real_malloc(size_t)真正分配內存,而后我們可以做搞點小動作。

同樣,我們可以wrap free。malloc跟free是配對的,當然也有其他相關API,比如calloc、realloc、valloc,但這根本上還是malloc+free,比如realloc就是malloc + free。

怎么去定位內存泄漏呢?

我們會malloc各種不同size的chunk,也就是每種不同size的chunk會有不同數量,如果我們能夠跟蹤每種size的chunk數量,那就可以知道哪種size的chunk在泄漏。很簡單,如果該size的chunk數量一直在增長,那它很可能泄漏。

光知道某種size的chunk泄漏了還不夠,我們得知道是哪個調用路徑上導致該size的chunk被分配,從而去檢查是不是正確釋放了。

怎么跟蹤到每種size的chunk數量?

我們可以維護一個全局 unsigned int malloc_map[1024 * 1024]數組,該數組的下標就是chunk的size,malloc_map[size]的值就對應到該size的chunk分配量。

這等于維護了一個chunk size到chunk count的映射表,它足夠快,而且它可以覆蓋到0 ~ 1M大小的chunk的范圍,它已經足夠大了,試想一次分配一兆的塊已經很恐怖了,可以覆蓋到大部分場景。

那大于1M的塊怎么辦呢?我們可以通過log記錄下來。

  • 在__wrap_malloc里,++malloc_map[size]
  • 在__wrap_free里,--malloc_map[size]

很簡單,我們通過malloc_map記錄了各size的chunk的分配量。

如何知道釋放的chunk的size?

不對,free(void *p)只有一個參數,我如何知道釋放的chunk的size呢?怎么辦?

我們通過在__wrap_malloc(size_t)的時候,分配8+size的chunk,也就是多分配8字節,開始的8字節存儲該chunk的size,然后返回的是(char*)chunk + 8,也就是偏移8個字節返回給調用malloc的應用程序。

這樣在free的時候,傳入參數void* p,我們把p往前移動8個字節,解引用就能得到該chunk的大小,而該大小值就是前一步,在__wrap_malloc的時候設置的size。

好了,我們真正做到記錄各size的chunk數量了,它就存在于malloc_map[1M]的數組中,假設64個字節的chunk一直在被分配,數量一直在增長,我們覺得該size的chunk很有可能泄漏,那怎么定位到是哪里調用過來的呢?

如何記錄調用鏈?

我們可以維護一個toplist數組,該數組假設有10個元素,它保存的是chunk數最大的10種size,這個很容易做到,通過對malloc_map取top 10就行。

然后我們在__wrap_malloc(size_t)里,測試該size是不是toplist之一,如果是的話,那我們通過glibc的backtrace把調用堆棧dump到log文件里去。

注意:這里不能再分配內存,所以你只能使用backtrace,而不能使用backtrace_symbols,這樣你只能得到調用堆棧的符號地址,而不是符號名。

如何把符號地址轉換成符號名,也就是對應到代碼行呢?

addr2line

addr2line工具可以做到,你可以追查到調用鏈,進而定位到內存泄漏的問題。

至此,你已經get到了整個核心思想。

當然,實際項目中,我們做的更多,我們不僅僅記錄了toplist size,還記錄了各size chunk的增量toplist,會記錄大塊的malloc/free,會wrap更多的API。

總結一下:通過wrap malloc/free + backtrace + addr2line,你就可以定位到內存泄漏了。

 

責任編輯:趙寧寧 來源: 碼磚雜役
相關推薦

2011-06-16 09:28:02

C++內存泄漏

2025-05-26 04:00:00

2015-04-17 10:35:51

c++c++程序內存泄漏檢測代碼

2024-12-19 14:42:15

C++內存泄漏內存管理

2010-01-28 10:33:10

C++開發程序

2020-11-02 09:48:35

C++泄漏代碼

2010-01-25 18:15:52

2010-01-25 14:56:08

C++程序

2023-12-27 13:55:00

C++內存分配機制new

2010-01-26 15:51:06

C++變量

2021-11-08 12:44:48

AndroidC++內存

2020-05-26 13:25:00

語言編譯代碼

2011-04-11 09:47:50

C++內存管理

2024-05-06 11:19:20

內存池計算機編程

2024-01-09 09:23:12

指針C++

2010-01-26 17:27:58

C++C程序

2011-05-13 18:10:55

CC++

2023-11-17 11:40:51

C++內存

2021-02-26 10:41:59

C++程序員代碼

2021-10-11 11:53:07

C++接口代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美日韩精品国产 | 天天搞天天操 | 91免费看片| 欧美日韩激情 | 在线免费观看亚洲 | 在线看av的网址 | 最新中文字幕久久 | 亚洲精品中文字幕 | 日本特黄特色aaa大片免费 | 亚洲视频在线一区 | 久久精品一区 | 在线观看成人小视频 | 亚洲最大av | 成人一级视频在线观看 | 亚洲国产成人久久久 | 日日夜夜草 | 在线免费观看日本视频 | 一级在线| 亚洲欧美视频 | 精品久草 | 欧美日韩电影一区二区 | 伊人色综合久久天天五月婷 | 精品三级在线观看 | 亚洲免费影院 | 欧美黄色一区 | 一区二区三区中文字幕 | 91视视频在线观看入口直接观看 | 99精彩视频 | 欧美11一13sex性hd | 视频一区二区三区中文字幕 | 小草久久久久久久久爱六 | 亚洲一二视频 | av天天看 | 日韩欧美在线免费观看视频 | 日本在线视频一区二区 | 日本精品免费在线观看 | 天天爽夜夜操 | 婷婷国产一区二区三区 | 成人网在线观看 | 日韩成人在线观看 | 亚洲精品一区二区三区蜜桃久 |