快有幾個月沒更新了,記錄一下最近解決問題用到的工具吧.html
最近代碼跑壓力測試,老是發現內存在無規律的慢慢增長,所以在Android上用上了大名頂頂的valgrind,說實話,真是名不虛傳,java
真是建議之後全部c/c++ 項目,無論有沒有現象級的問題,用這個跑一下檢測下一些隱藏得比較深的問題;linux
export G_SLICE=always-malloc c++
export G_DEBUG=gc-friendly 正則表達式
注:Android 4.4中跑valgrind ,把external中編譯的valgrind拷貝到小程序
/data/valgrind目錄,而後設置環境變量才能使用:多線程
export VALGRIND_LIB=/usbdisk/valgrind函數
參考命令行:工具
valgrind -v --tool=memcheck --track-fds=yes --leak-check=full --show-reachable=yes --time-stamp=yes --undef-value-errors=no --malloc-fill=0xc --free-fill=0xd --freelist-vol=100000000 --trace-children=yes --num-callers=50 --suppressions=default.supp --log-file=valgrind_gst ./cmdplayer -p gstreamer http://10.9.44.116/test.mp4
注:性能
Android 的external目錄下有valgrind的源代碼,mm 編譯後拷貝到板子上就可使用valgrind了.
1,生成supp文件
supp文件能夠定義valgrind的檢查過濾規則。若是你確實用過valgrind,你會發現其對內存的檢查很是嚴厲,很容易存在誤報(其實也不是誤報,有時候那些錯誤只是你不關注的),尤爲是對於libc中的malloc與free(好像還有new和delete,另外這個是個很tricky的地方,按照文檔的意思是,libc裏面malloc時,會額外分配一點內存用於某些事情來保證malloc的工做,而這些額外的內存不會被free釋放掉,由於當線程釋放的時候,linux內核會將這些額外的內存給釋放了,從而內存檢測工具的檢查會被影響)以及一些其餘的庫(好比ACE?)。爲了消除這些干擾信息,你須要生成supp文件。最簡單的辦法就是在啓動valgrind的時候加上選項--gen-suppressions=all,再將生成的規則複製出來。固然,這不是一個聰明的辦法。最好是將生成的結果整理一下,將多個類似的整理成一條。能夠參考官方文檔suppressing errors
2,對程序的影響
若是你編寫的只是小型程序,你能夠不關注這一部分。但若是是大型程序(尤爲對性能有要求的)或者是多線程程序(大型程序應該都這樣吧),你的程序會工做起來後有些不一樣。第一,變的很是很是慢。valgrind模擬的一個軟CPU,將可執行程序運行在其中。因此效率很低,速度慢不少,並且,valgrind的是單線程的(應該是),它會將你程序的全部線程統一管理起來,其實就是強制串行起來執行。因此你必定要明白這一點,用valgrind跑你的程序時,若是testcase掛掉了,看看是否是和性能有關的那些。
另外,請注意,64位的valgrind,不能執行32位的程序。這一點我沒有嚴格驗證過,也多是版本沒有更新的緣由,至少在我調試時,64位的rhel系統下,產品的64位的程序會建立2個32位的子進程,而後掛在那裏,沒有錯誤也沒有警告。
3,多進程追蹤
若是你只是一個單一的小程序,不用開子進程,valgrind挺好用的。若是你要用valgrind去追蹤多進程程序中的內存泄露,就有點繁瑣了。有幾個選項要特別注意。
--trace-children=yes 這個是必須的,打開追蹤子進程
--log-file=<filename> --xml-file=<filename> 文本格式報告和xml格式報告的報告名稱,推薦使用%p_log.memcheck之類的名字,%p會被valgrind轉義成進程號,這樣每個進程都擁有一份獨立的報告。
--child-silent-after-fork=yes 這個看狀況,若是不打開的話,報告會更詳細,錯誤定位可能會更精準,可是多份報告會混雜在一塊兒,會直接破壞xml格式的報告
--trace-children-skip=patt1,patt2,... --trace-children-skip-by-arg=patt1,patt2,... 若是不使用這個,valgrind會追蹤全部子進程,哪怕這個進程是java的。因此對應的,你須要讓valgrind過濾一些子進程,--trace-children-skip是根據exec的file/path中的字符串匹配來過濾,--trace-children-skip-by-arg是根據exec的argv參數來過濾。沒有正則表達式,只有*,?匹配兩個符號可用。
另外,對於被執行程序而言,valgrind是other權限組的,因此記得更改執行權限。而後valgrind的報告會生成在,啓動valgrind時用戶所在的目錄處。子進程的報告會生成在子進程程序所在目錄。例如若是java在/bin/下,這報告會生成在/bin/裏。但若是valgrind沒有su權限,則報告會沒法生成。
4,報告結果顯示
其實valgrind的報告結果是很詳細的。可是不要認爲那些開發team願意去一條條閱讀valgrind的內存錯誤結果報告。因此,圖形化顯示結果是很重要的。幸運的是,Jenkins中已經包含了valgrind插件,並且很是好用。
安裝valgrind插件:進入系統管理,插件管理中,在可選插件中搜索valgrind,而後安裝便可。
配置valgrind插件:插件的默認工做目錄是Jenkins的工做目錄,因此要顯示結果須要將valgrind的報告結果複製入Jenkins的工做目錄。這裏須要的報告結果是xml格式的。Report Pattern: 設置檢索報告的命名格式,通常生成的報告若是是%p_log.memcheck,那麼這裏就設置爲*_log.memcheck.
配置好以後,在配置的下方,會出現valgrind Results。當每次構建完成以後,點擊進入後均可以看到當前內存錯誤數量的圖表,以及每一個錯誤的函數名、函數調用關係等。