首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

資源洩露檢測工具進化史:從侵入式記錄到 Hook 透明化與效能優化

     編輯:關於C語言

第一版痛點

  • 效能差:每次分配都記錄完整呼叫堆疊(檔名、函數名、行號),多次分配記憶體保存資訊,但洩露機率低,資訊利用率極低,嚴重拖慢測試效率。
  • 侵入性強:需修改原始碼初始化、記錄指標/大小、釋放時從鏈表刪除、選擇位置列印。換版本、換專案每次都要改,繁瑣易出錯,最終被放棄。

核心突破:ILT Hook 技術

Windows 函數調用機制

Debug 版本下,呼叫函數 → call @ILT+offset → ILT 表中 jmp 實際函數位址。修改 ILT 中的 jmp 目標位址即可實現 Hook。

關鍵細節:相對位址跳轉

E9 26 00 00 00  // jmp 相對位移 0x26
目標位址 = 當前指令位址 + 5(指令長度) + 相對位移

Hook 時需計算新函數相對於 ILT 條目的位移,而非直接填寫絕對位址。

Hook 範例:將 test1 導向 test2

void hookfunc() {
    LPBYTE p1 = (LPBYTE)test1 + 1;  // 跳過 E9
    LPBYTE p2 = (LPBYTE)test2 + 1;
    DWORD newRel = (DWORD)p2 - (DWORD)p1;  // 計算相對位移
    WriteProcessMemory(GetCurrentProcess(), p1, &newRel, 4, NULL);
}

保留原函數調用能力

交換 ILT 中 test1/test2 的 jmp 指令:顯式呼叫 test1 實際進入 test2,呼叫 test2 實際進入 test1。Hook 函數通常不被直接呼叫,故無副作用。

工具透明化:DLL + #pragma comment 自動初始化

  • DLL 導出全域檢測器物件 ResourceLeakDetector rld。
  • 頭檔雙 #pragma:
    #pragma comment(linker, "/include:__imp_?rld@@3VResourceLeakDetector@@A") 強制包含物件
    #pragma comment(lib, "rld.lib") 自動鏈接庫
  • 使用者僅需 #include "rld.h" 即可零侵入啟用檢測。

效能優化:延遲符號解析

只記錄位移:分配時僅存指令位址偏移,不解析檔名/函數名(耗時)。
洩露時再解析:最終報告階段根據偏移查符號表,大幅降低常規路徑開銷。

相容性修復

  • 中文路徑截斷 → 更新 DbgHelp.dll 至新版支援寬字元解析。
  • Vista 下無堆疊 → 同樣更新 DbgHelp.dll 解決。

來源:「越測越開心」博客,原文連結:https://happytest.blog.51cto.com/324097/62791。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved