TDengine研發分享 Windbg解決記憶體洩漏問題的實踐和經驗

Mondo 科技 更新 2024-02-28

記憶體洩漏是乙個常見的問題,它會導致程式的記憶體占用逐漸增加,最終導致系統資源耗盡或程式崩潰。 AddressSanitizer (ASAN) 和 Valgrind 是很好的記憶體檢測工具,TDengine 的 CI 程序使用 ASAN。 不過,這次記憶體洩漏問題發生在Windows下,我們的CI還沒有覆蓋,所以TDENGINE研發選擇使用WindBG來解決這個問題。 事實證明,在Windows下,使用WindBG也是乙個不錯的選擇。

記憶體洩漏通常發生在以下情況下:

程式未正確釋放分配的記憶體。

程式中存在迴圈引用,這些迴圈引用會導致垃圾回收器記憶體失敗。

程式中存在記憶體洩漏的第三方庫或元件。

記憶體洩漏的主要檢測方法如下:

靜態分析工具:程式執行時未檢測到記憶體動態分配的指標或記憶體分配錯誤等問題。

動態分析工具:您可以使用記憶體分配和釋放***來跟蹤程式中的記憶體分配和釋放操作,並檢測是否存在記憶體洩漏。 但是,使用某些工具(例如 Valgrind)可能會對程式的效能產生一些影響。

偵錯程式:windbg 和 gdb。

優點和缺點:

靜態分析工具可以及早發現問題,但它們無法檢測程式執行時記憶體的動態分配方式。

動態分析工具可以在程式執行時檢測問題,但它們會影響程式效能,並且在檢測大型應用程式時可能需要大量時間和資源。 但是,在資源充足的測試環境中執行不是問題,例如,ASAN 幫助我們發現了很多問題。

偵錯程式可以在程式執行時檢測問題,並提供強大的分析工具。

使用 windbg 定位記憶體洩漏,依靠 GLAGS 元件來記錄程式在執行時請求和釋放的所有記憶體,以及請求記憶體時的呼叫堆疊資訊。 這樣,在程式執行過程中,umdh元件用於記錄兩個快照,通過比較兩個快照之間的差異,可以找出在兩個快照之間的時間間隔內應用但未釋放的記憶體應用資訊。 如果存在記憶體洩漏,則差異結果的第一條邊通常是洩漏點處的呼叫堆疊資訊。 當然,在兩次快照期間,應該盡可能地觸發記憶體洩漏,以便更準確地定位它。 diff 結果中也會有少量的呼叫訊息,正常應用還沒來得及發布,但是在 diff 結果中可以看到呼叫的數量,更容易識別。

在 Windows 中匯入資料時出現 taosdump 錯誤:

build and install latest tdengine 3.0 branch on windowsuse "taosbenchmark -i stmt -y" to create a lot of tables and data (10000 * 10000).use "taosdump -d test -o outputfile" to dump outuse "taos -s 'drop database test'" to drop databaseuse "taosdump -i inputfile" to dump in.
錯誤日誌:taosd “tsem init failed, errno: 28”。

taosdump: dumpin**rodataimpl() ln7039 taos_stmt_execute() failed! reason: out of memory, timestamp: 1500000009256

Gflags 工具應位於以下路徑: C:程式檔案 (x86) Windows Kits 10 偵錯程式 x64 Gflags,如果沒有,可以直接進入 Microsoft 的官方 *** 安裝:

安裝完成後,執行 gflags。 命令列exe /i your_application.exe 可以設定跟蹤目標並設定相關引數。 也可以雙擊執行,影象檔案對應 i 引數,然後選擇您的應用程式啟動器exe,然後選擇其他配置。

1.啟動應用程式exe (我正在除錯 taosdumpexe,所以底部是 taosdumpexe)

c:\program files (x86)\windows kits\10\debuggers\x64\gflags” -i taosdump.exe +ust

2.將 pdb 檔案複製到 mysymbols 目錄下,pdb 檔案儲存了編譯程式的除錯資訊,這些資訊是用可執行程式生成的,可以在應用生成目錄中找到。

3.設定 pdb 目錄。

set _nt_symbol_path=c:\mysymbols;srv*c:\mycache*
4.拍攝第乙個記憶體快照。

"c:\program files (x86)\windows kits\10\debuggers\x64\umdh" -pn:taosdump.exe -f:c:\xstest\umdhlog\taosdump11.log
5.拍攝第二個記憶體快照。

"c:\program files (x86)\windows kits\10\debuggers\x64\umdh" -pn:taosdump.exe -f:c:\xstest\umdhlog\taosdump12.log
6.生成快照比較結果 (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
由於 taosdump 程式從開始到退出都在執行大量業務工作,因此快照之間很容易發生記憶體洩漏。 988040 6ecf0 表示“應用程式數量發布數量”,很明顯發生了記憶體洩漏,洩漏點在 buildrequest 函式的 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!dumpin**rodataimpl+e25 (c:\workroom\tdengine\tools\taos-tools\src\taosdump.c, 6260) taosdump!dumpinone**rofile+3d2 (c:\workroom\tdengine\tools\taos-tools\src\taosdump.c, 7229) taosdump!dumpin**roworkthreadfp+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+9c (minkernel\crts\ucrt\src\appcrt\startup\thread.cpp, 97) kernel32!basethreadinitthunk+10 ntdll!rtluserthreadstart+2b
接下來勾選**並修改,C語言使用記憶體的自由度很高,所以也比較麻煩。 您可以看到某些路徑錯過了對 tsem destory 的呼叫。

欲瞭解更多詳情,請看這裡

要想做好,首先要磨礪你的工具,掌握更多的工具和手段,更冷靜地解決問題,windbg定位記憶體洩漏的方法很簡單,但非常有效。 但是,請務必注意,它依賴於 pdb 檔案,因此請記住在發布應用程式時保留 pdb 檔案。 pdb 檔案包含有關程式的符號資訊,這有助於我們在除錯過程中查明問題。

另外,從**問題可以看出,這個記憶體的管理還是比較容易出錯的,RAII機制可以更好的避免資源洩漏,C語言也可以通過模擬RAII達到類似的效果,雖然不如C++流暢,但也許以後可以考慮優化一下。

RAII(Resource Acquisition is Initialization)機制是一種重要的資源管理方法,它將資源的獲取與物件的生命週期相關聯。 通過在物件的建構函式中獲取資源並在析構函式中釋放資源,我們可以確保資源的正確管理,並防止資源洩漏和記憶體洩漏等問題。 RAII機制廣泛應用於C++等程式語言中,是管理資源的有效方式。

相關問題答案

    展位火爆!TDengine受邀參加EDT2023中國能源和化工行業數字技術峰會

    隨著大資料 物聯網 人工智慧 G等數字技術的蓬勃發展,能源化工與新興技術的融合也在加速推進,推動智慧型化 網格化 資訊化加速演進。在不穩定的外部環境下,數位化轉型成為能源化工企業可持續發展的關鍵。月日,由辰哲文化主辦的 EDT中國能源化工數位化技術峰會 在北京舉行,峰會邀請了來自能源化工行業資訊科技...

    TDengine與西電電力簽約

    近年來,隨著雲計算和物聯網技術的快速發展,傳統電力行業正朝著數位化 資訊化 智慧型化的大趨勢邁進。電力行業在傳統業務基礎上,構建了資訊網路 通訊網路和能源網路,致力於實現發電 輸電 變電 配電 用電的實時智慧型聯動。在此過程中,電力物聯網領域產生的資料採集量呈現出一流的增長態勢,應對海量資料處理需求...

    TDengine與吉誠電子簽約

    隨著電力系統的複雜度和資料量的增加,電力負載 電壓 頻率等海量時序資料需要更高效的儲存和處理能力,以保證資料的可靠性和實時性。此外,電力系統還需要對實時資料進行快速分析和決策,以確保電網的穩定執行。然而,傳統的資料處理解決方案往往難以滿足這些資料處理需求。為了應對這些挑戰,越來越多的公用事業公司正在...

    百色茶館網際網絡研發團隊分享傳統企業數位化公升級

    年是 web 年。今年是數位化公升級 智慧型化傳統企業的關鍵一年,也是傳統企業同行業競爭 元宇宙時代重新崛起的劃時代之年 數位化 業務資料化 首先允許通過資料記錄業務流程。數位化 業務數位化 即讓企業在生產 採購 銷售過程 客戶服務 現金流等過程中產生的資料,用資料記錄在業務系統上。首先,資訊化 數...

    TDengine與中船集團9號簽約,助力航運業智慧型化轉型公升級

    在大資料時代,船舶智慧型化已成為造船和航運發展的必然趨勢。作為 中國製造 中明確的重點發展領域,智慧型船舶代表著船舶的未來發展方向,對航運業轉型公升級至關重要。其中,大資料的處理和應用成為船舶智慧型化改造成功的關鍵因素之一。近日,TDEngine 與中國船舶第九研究院第九設計研究院,以下簡稱中國船舶...