Linux 下 C++ 缺乏類似 MSVC `_CrtDumpMemoryLeaks()` 的內置洩漏報告機制。本文系統闡述**自研內存檢測子系統**的設計與實現:重載全局 `operator new/delete` 截獲分配釋放、利用 `__FILE__/__LINE__` 定位源碼、構建線程安全的分配映射表、程序退出時輸出洩漏報告、動態快照監控長期運行洩漏、識別 `new[]/delete` 不匹配等高級主題,並提供一個高性能互斥體實現。
new operator:計算大小 → 調用 operator new(size_t) 分配原始內存 → 調用構造函數。delete operator:調用析構函數 → 調用 operator delete(void*) 釋放內存。operator new、operator new[]、operator delete、operator delete[]void* operator new(size_t nSize, const char* pszFileName, int nLineNum) {
void* p = ::operator new(nSize); // 調用全局分配
g_allocMap.insert({p, {pszFileName, nLineNum, nSize}}); // 記錄
return p;
}
void* operator new[](size_t nSize, const char* pszFileName, int nLineNum) { ... }
void operator delete(void* p) noexcept {
auto it = g_allocMap.find(p);
if (it != g_allocMap.end()) {
g_allocMap.erase(it);
}
::operator delete(p);
}
void operator delete[](void* p) noexcept { ... }
頭文件 MemRecord.h:
#define DEBUG_NEW new(__FILE__, __LINE__)
#if defined(MEM_DEBUG)
#define new DEBUG_NEW
#define delete DEBUG_DELETE // 見下文
#endif
用戶代碼編譯時加 -DMEM_DEBUG 即啟用檢測,發布版去掉開關零開銷。
定義全局對象 CMemoryTracker g_tracker,構造函數初始化映射表與鎖,析構函數遍歷殘留映射輸出洩漏報告。保證**先於用戶代碼構造、後於用戶代碼析構**。
// 全局變量記錄 delete 調用位置
char g_deleteFile[256] = {0};
int g_deleteLine = 0;
CMutex g_deleteLock;
// 宏替換 delete
#define DEBUG_DELETE \
g_deleteLock.Lock(); \
strncpy(g_deleteFile, __FILE__, 255); \
g_deleteLine = __LINE__; \
delete
// operator delete 內部
void operator delete(void* p) {
g_deleteLock.Lock();
const char* file = g_deleteFile;
int line = g_deleteLine;
g_deleteFile[0] = 0; g_deleteLine = 0;
g_deleteLock.Unlock();
if (g_allocMap.find(p) == g_allocMap.end()) {
// 找不到原分配記錄 → 疑似不匹配刪除
LogWarning("Mismatched delete at %s:%d ptr=%p", file, line, p);
}
// ... 正常清理
}
原則:**寧可誤報,不可漏報**。第三方庫無宏定義時不觸發警告(全局變量為零)。
MemSnapShot:讀取消息隊列,維護內存分配統計表(Key:文件:行號,Value:當前未釋放字節數、佔比)。為避免 `pthread_mutex_t` 在高併發分配下的內核態切換開銷,實現 CCommonMutex:
N 次(適應短臨界區)。sem_wait 進入內核等待。sem_post 喚醒。MemRecord.h 並啟用宏。-DMEM_DEBUG,Release 不加。MemSnapShot 旁路監控,定期導出動態增長報告。通過**編譯期宏注入、運行期映射跟蹤、消息隊列旁路監控**三層機制,在不修改業務邏輯、生產版零開銷的前提下,賦予 Linux C++ 項目企業級的內存洩漏檢測能力。核心代碼約 500 行,可直接集成至項目公共庫。