六月婷婷AV,国产偷窥猎奇福利二区,日韩三级片。,好吊色网站,日韩成人中文在线视频,国产亚洲午夜啪啪,亚洲欧美另类国产精品,国产成人av1,任你艹在线观看

內(nèi)存泄漏治理實(shí)戰(zhàn):TDengine 研發(fā)團(tuán)隊(duì)使用 Windbg 的經(jīng)驗(yàn)分享

內(nèi)存泄漏是一種常見的問題,它會導(dǎo)致程序的內(nèi)存占用逐漸增加,最終導(dǎo)致系統(tǒng)資源耗盡或程序崩潰。AddressSanitizer (ASan) 和 Valgrind 是很好的內(nèi)存檢測工具,TDengine 的 CI 過程就使用了 ASan 。不過這次內(nèi)存泄漏問題發(fā)生在 Windows 下,我們 CI 暫時(shí)還沒有覆蓋到,因此 TDengine 研發(fā)選擇使用 Windbg 來解決問題。結(jié)果證明,在 Windows 下,使用 Windbg 也是一個(gè)不錯(cuò)的選擇。

內(nèi)存泄漏的常用檢測方法

內(nèi)存泄漏通常會發(fā)生在以下情況下:

  • 程序未正確釋放已分配的內(nèi)存
  • 程序中存在循環(huán)引用,導(dǎo)致垃圾收集器無法回收內(nèi)存
  • 程序中存在內(nèi)存泄漏的第三方庫或組件

內(nèi)存泄漏的檢測方法主要包括以下幾種:

  1. 靜態(tài)代碼分析工具:未釋放的指針或內(nèi)存分配錯(cuò)誤等問題,不能檢測在程序運(yùn)行時(shí)動態(tài)分配內(nèi)存的情況。
  2. 動態(tài)分析工具:可以使用內(nèi)存分配和釋放跟蹤器來跟蹤程序中的內(nèi)存分配和釋放操作,并檢測是否存在內(nèi)存泄漏的情況。然而,使用某些工具(如Valgrind)可能會對程序的性能產(chǎn)生一定的影響。
  3. 調(diào)試器:WinDbg 和 GDB。

優(yōu)缺點(diǎn):

  • 靜態(tài)代碼分析工具可以在早期發(fā)現(xiàn)問題,但是它們不能檢測程序運(yùn)行時(shí)動態(tài)分配內(nèi)存的情況。
  • 動態(tài)分析工具可以在程序運(yùn)行時(shí)檢測問題,但是它們可能會影響程序性能,并且在檢測大型應(yīng)用程序時(shí)可能需要大量的時(shí)間和資源。不過在資源充足的測試環(huán)境中跑的話,就都不是問題了,比如 ASan 就幫我們發(fā)現(xiàn)過不少問題。
  • 調(diào)試器可以在程序運(yùn)行時(shí)檢測問題,并提供強(qiáng)大的分析工具。

實(shí)踐分析

基本原理

使用 Windbg 定位內(nèi)存泄露,依賴 glags 組件記錄程序在運(yùn)行期間所有申請和釋放的內(nèi)存,同時(shí)記錄的還有申請內(nèi)存時(shí)的調(diào)用棧信息。這樣在程序運(yùn)行期間,使用 umdh 組件進(jìn)行兩次快照記錄,通過比較兩次快照信息的差異,就可以發(fā)現(xiàn)兩次快照間隔時(shí)間段中申請卻并未釋放的內(nèi)存申請信息。如果有內(nèi)存泄露,diff 結(jié)果最前邊一般就是泄漏點(diǎn)的調(diào)用棧信息。當(dāng)然,兩次快照期間,要盡量觸發(fā)內(nèi)存泄露,才能更準(zhǔn)確的定位。diff 結(jié)果中還會有少量正常的申請沒來得及釋放的調(diào)用信息,不過 diff 結(jié)果中能看到調(diào)用次數(shù),比較容易甄別。

問題介紹

taosdump 在 windows 導(dǎo)入數(shù)據(jù)出錯(cuò):

build and install latest TDengine 3.0 branch on Windows
use "taosBenchmark -I stmt -y" to create a lot of tables and data (10000 * 10000).
use "taosdump -D test -o outputFile" to dump out
use "taos -s 'drop database test'" to drop database
use "taosdump -i inputFile" to dump in.

錯(cuò)誤日志:taosd “tsem_init failed, errno: 28”

Taosdump: dumpInAvroDataImpl() LN7039 taos_stmt_execute() failed! reason: Out of Memory, timestamp: 1500000009256

定位過程

配置 gflags

gflags 工具應(yīng)該位于路徑:C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags,如果沒有的話,可以直接前往 Microsoft 的官方網(wǎng)站下載安裝:https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/debugger-download-tools

安裝完成后,在命令行執(zhí)行 gflags.exe /i your_application.exe 可設(shè)置跟蹤目標(biāo),同時(shí)可以設(shè)置相關(guān)參數(shù)。雙擊運(yùn)行也是可以的,Image File 對應(yīng) /i 參數(shù),選擇啟動程序 your_application.exe 后先按 tab 鍵,然后選擇其他配置。

內(nèi)存泄漏治理實(shí)戰(zhàn):TDengine 研發(fā)團(tuán)隊(duì)使用 Windbg 的經(jīng)驗(yàn)分享 - TDengine Database 時(shí)序數(shù)據(jù)庫

定位步驟
  1. 啟動 your_application.exe(我要調(diào)試的是 taosdump.exe,所以下邊是 taosdump.exe)

“C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags” -i taosdump.exe +ust

  1. 拷貝 pdb 文件到 mysymbols 目錄,pdb 文件存儲了編譯后的程序的調(diào)試信息,和可執(zhí)行程序一起生成,可以在應(yīng)用程序生成目錄中找到。
  2. Set pdb 目錄
set _NT_SYMBOL_PATH=c:\mysymbols;srv*c:\mycache*https://msdl.microsoft.com/download/symbols
  1. 生成第一次內(nèi)存快照
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\umdh" -pn:taosdump.exe -f:C:\xstest\umdhlog\taosdump11.log
  1. 生成第二次內(nèi)存快照
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\umdh" -pn:taosdump.exe -f:C:\xstest\umdhlog\taosdump12.log
  1. 生成快照比較結(jié)果(umdh)
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\umdh"  C:\xstest\umdhlog\taosdump11.log C:\xstest\umdhlog\taosdump12.log -f:C:\xstest\umdhlog\taosdumpdiff11_12.log

分析與解決

結(jié)果文件

因?yàn)?taosdump 程序啟動后直至退出都在做大量的業(yè)務(wù)工作,內(nèi)存泄露很容易發(fā)生在兩次快照期間。 988040 – 6ecf0 表示”申請次數(shù) – 釋放次數(shù)”, 很明顯發(fā)生了內(nèi)存泄露,泄漏點(diǎn)在 buildRequest 函數(shù)的 sem_init 這里。

+  919350 ( 988040 - 6ecf0)  201b0 allocs        BackTrace9CB6973F
+   1ea5c ( 201b0 -  1754)        BackTrace9CB6973F        allocations

        ntdll!RtlpAllocateHeapInternal+948D5
        taos!heap_alloc_dbg_internal+1F6 (minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp, 359)
        taos!heap_alloc_dbg+4D (minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp, 450)
        taos!_calloc_dbg+6C (minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp, 518)
        taos!calloc+2E (minkernel\crts\ucrt\src\appcrt\heap\calloc.cpp, 30)
        taos!sem_init+5D (C:\workroom\TDengine\contrib\pthread\sem_init.c, 109)
        taos!buildRequest+209 (C:\workroom\TDengine\source\client\src\clientImpl.c, 192)
        taos!stmtCreateRequest+73 (C:\workroom\TDengine\source\client\src\clientStmt.c, 15)
        taos!stmtSetTbName+115 (C:\workroom\TDengine\source\client\src\clientStmt.c, 588)
        taos!taos_stmt_set_tbname+7F (C:\workroom\TDengine\source\client\src\clientMain.c, 1350)
        taosdump!dumpInAvroDataImpl+E25 (C:\workroom\TDengine\tools\taos-tools\src\taosdump.c, 6260)
        taosdump!dumpInOneAvroFile+3D2 (C:\workroom\TDengine\tools\taos-tools\src\taosdump.c, 7229)
        taosdump!dumpInAvroWorkThreadFp+20B (C:\workroom\TDengine\tools\taos-tools\src\taosdump.c, 7306)
        taosdump!ptw32_threadStart+CD (C:\workroom\TDengine\contrib\pthread\ptw32_threadStart.c, 233)
        taosdump!thread_start<unsigned int (__cdecl*)(void *),1>+9C (minkernel\crts\ucrt\src\appcrt\startup\thread.cpp, 97)
        KERNEL32!BaseThreadInitThunk+10
        ntdll!RtlUserThreadStart+2B
泄漏點(diǎn)修改

接下來查看代碼并修改,C 語言對內(nèi)存的使用自由度很高,因此也比較麻煩。可以看到有些路徑遺漏了 tsem_destory 的調(diào)用。

內(nèi)存泄漏治理實(shí)戰(zhàn):TDengine 研發(fā)團(tuán)隊(duì)使用 Windbg 的經(jīng)驗(yàn)分享 - TDengine Database 時(shí)序數(shù)據(jù)庫

更加詳細(xì)的代碼方案請見 https://github.com/taosdata/TDengine/pull/19580

總結(jié)

工欲善其事必先利其器,掌握更多的工具和手段,在解決問題時(shí)才能比較從容,Windbg 定位內(nèi)存泄漏的方式非常簡單,但是很有效。不過需要注意,它依賴 pdb 文件,因此,發(fā)布應(yīng)用程序時(shí)要記得保留 pdb 文件。pdb 文件包含了程序的符號信息,能夠幫助我們在調(diào)試過程中準(zhǔn)確定位問題所在。

另外,從出問題的代碼可以看出,這塊內(nèi)存的管理方式還是比較容易出錯(cuò),RAII 機(jī)制能較好的避免資源泄露,C 語言中也可以通過模擬 RAII 來達(dá)到類似的效果,雖然沒有 C++ 那么流暢,也許以后可以考慮優(yōu)化一下。

RAII(Resource Acquisition Is Initialization)機(jī)制是一種重要的資源管理方式,它將資源的獲取和對象的生命周期關(guān)聯(lián)起來。通過在對象的構(gòu)造函數(shù)中獲取資源,在析構(gòu)函數(shù)中釋放資源,我們可以確保資源的正確管理,防止資源泄漏和內(nèi)存泄漏等問題。RAII 機(jī)制在 C++ 等編程語言中得到廣泛應(yīng)用,是一種有效的資源管理方式。