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

C語言輕量級記憶體洩漏檢測工具實現

     編輯:關於C

在開發調試階段,快速定位同模組、同線程的記憶體洩漏至關重要。本文實現一個基於鏈表記錄分配/釋放的簡易檢測工具,通過宏替換標準庫函數,零侵入式集成到項目中。

核心設計

  1. 取消標準宏定義:#undef malloc/free/calloc 避免衝突。
  2. 鏈表節點結構:記錄位址、大小、行號、檔名、下一節點指針。
  3. 攔截封裝函數:
    • dbg_malloc(size, file, line):分配後插入鏈表頭。
    • dbg_calloc(count, size, file, line):同理,計算總大小。
    • dbg_free(ptr):釋放記憶體並從鏈表移除節點。
  4. 報告生成:show_block() 遍歷鏈表輸出洩漏位置、位址、大小,並統計總量。

關鍵代碼片段

頭文件 memcheck.h

#ifndef _MEM_CHECK_H
#define _MEM_CHECK_H
#include <stdlib.h>

#define malloc(s)     dbg_malloc(s, __FILE__, __LINE__)
#define calloc(c, s)  dbg_calloc(c, s, __FILE__, __LINE__)
#define free(p)       dbg_free(p)

void *dbg_malloc(size_t size, const char *file, size_t line);
void *dbg_calloc(size_t count, size_t size, const char *file, size_t line);
void dbg_free(void *ptr);
void show_block(void);
#endif

實現文件 memcheck.c 核心邏輯

static mem_node *head = NULL;

static void mem_node_add(void *ptr, size_t block, size_t line, const char *file) {
    mem_node *node = malloc(sizeof(mem_node));
    node->ptr = ptr; node->block = block; node->line = line; node->filename = file;
    node->next = head; head = node;
}

static void mem_node_remove(void *ptr) {
    if (!head) return;
    if (head->ptr == ptr) { head = head->next; free(ptr); return; }
    mem_node *prev = head, *curr = head->next;
    while (curr) {
        if (curr->ptr == ptr) { prev->next = curr->next; free(curr); return; }
        prev = curr; curr = curr->next;
    }
}

void show_block() {
    if (!head) return;
    size_t total = 0;
    puts("\n--- 記憶體洩漏報告 ---");
    for (mem_node *p = head; p; p = p->next) {
        const char *file = strrchr(p->filename, '\\'); // 簡化路徑顯示
        file = file ? file + 1 : p->filename;
        printf("位置: %s(%zu), 位址: %p (%zu bytes)\n", file, p->line, p->ptr, p->block);
        total += p->block;
    }
    printf("總計洩漏: %zu bytes\n", total);
}

使用方法

  1. 將 memcheck.c 加入專案編譯。
  2. 在需檢測的源文件頂部包含 #include "memcheck.h"(建議僅在 DEBUG 模式下)。
  3. 程式入口處註冊退出報告:atexit(show_block);。
#ifdef DEBUG
#include "memcheck.h"
#endif

int main() {
#ifdef DEBUG
    atexit(show_block);
#endif
    int *p = malloc(1000); // 故意不釋放
    return 0;
}

輸出示例

--- 記憶體洩漏報告 ---
位置: main.c(10), 位址: 0x55a3c8 (1000 bytes)
總計洩漏: 1000 bytes

局限與擴展

  • 僅支援單線程、單模組,多線程需加鎖。
  • 無法檢測 realloc、new/delete(C++)、系統級分配。
  • 生產環境建議使用 Valgrind、AddressSanitizer 等專業工具。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved