日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

使用valgrind检测ATS插件中的内存泄露

發布時間:2023/11/27 生活经验 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用valgrind检测ATS插件中的内存泄露 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.內存錯誤出現的場景

這幾天在重構ATS插件代碼的過程中遇到了煩人的內存泄露問題, 周五周六連續兩天通過走查代碼的方法,未能看出明顯的導致內存錯誤的代碼, 同時也覺得C和C++混合編程得到一個動態庫, 在一個.cpp主文件中,即用new又用malloc來動態分配內存, 可能會導致內存錯誤.后來網上調研和查資料發現, new和malloc混用還是允許的,因為C++兼容C.雖然這種混用方式不提倡, 但絕對不會導致內存堆棧錯亂的情況.

這里之所以采用C和C++混合編程,是因為業務需要. ATS插件目前設計為一個transform主框架, 外加若干子模塊, 一個子模塊一個動態庫,后者可以根據不同業務需要進行擴展,而transform類型的插件框架一般不變, 它只完成通常的transform變換流程就可以了. 這個主框架是使用C++開發的, 它提供了業務實現接口, 供每個業務動態庫實現.因為接口入參中用到了stl的map結構來在主框架和子模塊之間傳遞參數,所以接口的實現必須是C++方式的. 但是我的一個業務插件原來是使用純c編寫的, 引用了幾個第三方庫,比如JSON, libz, pcre庫等, 它們原來已經用C編寫好了,并且經過測試發現是可靠的, 如果再換為C++實現一般不太現實, 也沒有必要. 這樣造成的局面就是, 目前只能C和C++進行混合編程, 對C提供的接口, 要在h文件中使用 extern "C"聲明, 并將實現存放在對應的c文件中.(這里必須要分離成兩個文件, 如果以前只有一個h文件就搞定的, 現在要分為h和c文件).在編譯出一個so時, 同時要外鏈其他的第三方基礎庫時, Makefile的編寫通常有些技巧的, 請參見我的博文

C和C++混合編程的Makefile的編寫!

這種情況下, 對C那部分的調用,我采用malloc和free來分配和釋放內存, 對上層接口那部分, 我在主cpp文件中使用new和delete來分配內存.這里明顯使得內存的使用更加復雜化了,但是不管怎樣,按理說這種做法還是行得通的.

但是在調試過程中,我卻發現了一個內存越界的錯誤, 每次提示的錯誤都不一樣, 但是顯示出錯的位置又沒有明顯的錯誤, 真是讓人摸不到頭腦, 搞不定了, 郁悶, 失敗至極.....

二.內存錯誤出現的表象

兩天的搜索無果, 讓我只能尋求內存檢測軟件的幫助. 我以前用過tcmalloc, 就是google的gperftools里面的一個工具,它會將系統默認的內存分配釋放函數替換為自己的函數再進行檢測,但是在這里不方便施展, 因為這里new和malloc都用上了, 所以我決定使用valgrind來檢測. 具體安裝使用方法,請參見

在Ubuntu 14.04 64bit上安裝Valgrind并檢查內存泄露

下面是ATS插件運行中崩潰時valgrind檢測的幾個錯誤截圖


該截圖告訴我們, pool_alloc(在mem_manage.c第17行)調用malloc分配了1813字節內存, find_replace_html(位于main.cpp第484行)函數使用memcpy從1808處開始要復制8個字節, 而事實上只能復制4字節,這會內存越界,導致非法的8字節寫入(越界寫入).


該截圖告訴我們,??pool_alloc(在mem_manage.c第17行)調用malloc分配了1813字節內存,pcre_exec(在?regex_lookup.h第45行)在1813字節后面越界讀取了1個字節.


該截圖告訴我們, 在分配的1813字節內部的1808字節處, 要非法讀取8字節內存(越界讀取)

三.內存錯誤的分析和確定

上面的截圖分析, 很明確地傳遞出內存越界讀取和越界寫入的錯誤, 但是我查看內存分配的地方, 沒有看到明顯的錯誤.但是多次調試顯示的內存錯誤大多顯示到memset這樣的地方, 將部分memset代碼注釋掉后, 程序能運行, 但是運行一段時間后,它還是會有段錯誤, 看來找到的位置不對, 而且上面截圖顯示的都是造成錯誤的表現, 不是真正造成內存出錯的地方.最后經過認真理解valgrind的錯誤提示, 和仔細地分析代碼, 終于定位到內存錯誤的真正地方不是malloc長度那里, 而是memset那里, 初始化內存的那個指針只能是一個void*或char*, 不能是一個結構體, 這就是內存錯誤的真正地方.

參見下面的截圖, 有內存錯誤的源碼截圖


改正內存錯誤的源碼截圖


改正后, 重新編譯調試, 一切正常, 運行很長時間, 都沒有再崩掉, 再次印證修改是正確的.而這個錯誤, 是一個大家看起來很可笑的問題, 所要大家編寫代碼時還是要提高修養和注意力,千萬不要馬虎寫代碼,否則會害死自己的.

四.回顧反思

bug不可怕, 犯錯不可恥, 但是仔細分析導致bug的原因, 吸取教訓并避免再犯才是最重要的. 另外一點是, 排錯的鍛煉和快速定位是一項職業素養, 越修bug越有收獲越能提高, 經歷越豐富自信心越強, 所以bug來了,我們還是得從容面對.

總結

以上是生活随笔為你收集整理的使用valgrind检测ATS插件中的内存泄露的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。