#include #include #include #include "leak_detector_c.h" // 取消宏定义,使用原始 malloc/calloc/free #undef malloc #undef calloc #undef free // 全局链表起始与当前位置指针 static MEM_LEAK *ptr_start = NULL; static MEM_LEAK *ptr_next = NULL; /* * 将分配的内存信息添加到链表中 */ void add(MEM_INFO alloc_info) { MEM_LEAK *mem_leak_info = NULL; // 分配一个新的链表节点 mem_leak_info = (MEM_LEAK *) malloc(sizeof(MEM_LEAK)); mem_leak_info->mem_info.address = alloc_info.address; mem_leak_info->mem_info.size = alloc_info.size; strcpy(mem_leak_info->mem_info.file_name, alloc_info.file_name); mem_leak_info->mem_info.line = alloc_info.line; mem_leak_info->next = NULL; // 如果是第一个节点 if (ptr_start == NULL) { ptr_start = mem_leak_info; ptr_next = ptr_start; } else { // 添加到链表末尾 ptr_next->next = mem_leak_info; ptr_next = ptr_next->next; } } /* * 根据位置索引从链表中删除内存记录 */ void erase(unsigned pos) { unsigned index = 0; MEM_LEAK *alloc_info, *temp; // 删除第一个节点 if (pos == 0) { MEM_LEAK *temp = ptr_start; ptr_start = ptr_start->next; free(temp); } else { // 删除中间或最后一个节点 for (index = 0, alloc_info = ptr_start; index < pos; alloc_info = alloc_info->next, ++index) { if (pos == index + 1) { temp = alloc_info->next; alloc_info->next = temp->next; free(temp); break; } } } } /* * 清空链表中所有内存记录 */ void clear() { MEM_LEAK *temp = ptr_start; MEM_LEAK *alloc_info = ptr_start; while (alloc_info != NULL) { alloc_info = alloc_info->next; free(temp); temp = alloc_info; } } /* * 自定义 malloc 函数:分配内存并记录来源信息 */ void *xmalloc(unsigned int size, const char *file, unsigned int line) { void *ptr = malloc(size); if (ptr != NULL) { add_mem_info(ptr, size, file, line); } return ptr; } /* * 自定义 calloc 函数:分配并初始化内存,同时记录信息 */ void *xcalloc(unsigned int elements, unsigned int size, const char *file, unsigned int line) { unsigned total_size; void *ptr = calloc(elements, size); if (ptr != NULL) { total_size = elements * size; add_mem_info(ptr, total_size, file, line); } return ptr; } /* * 自定义 free 函数:释放内存前先移除记录 */ void xfree(void *mem_ref) { remove_mem_info(mem_ref); // 移除记录 free(mem_ref); // 实际释放 } /* * 创建内存分配信息并添加到链表中 */ void add_mem_info(void *mem_ref, unsigned int size, const char *file, unsigned int line) { MEM_INFO mem_alloc_info; // 清空结构体,确保初始化干净 memset(&mem_alloc_info, 0, sizeof(mem_alloc_info)); mem_alloc_info.address = mem_ref; mem_alloc_info.size = size; strncpy(mem_alloc_info.file_name, file, FILE_NAME_LENGTH); mem_alloc_info.line = line; // 添加到链表中 add(mem_alloc_info); } /* * 从链表中移除某段已释放的内存记录 */ void remove_mem_info(void *mem_ref) { unsigned short index; MEM_LEAK *leak_info = ptr_start; // 遍历链表查找目标地址 for (index = 0; leak_info != NULL; ++index, leak_info = leak_info->next) { if (leak_info->mem_info.address == mem_ref) { erase(index); // 找到后删除 break; } } } /* * 将所有未释放的内存信息写入输出文件 */ void report_mem_leak(void) { MEM_LEAK *leak_info; FILE *fp_write = fopen(OUTPUT_FILE, "wt"); if (fp_write != NULL) { fprintf(fp_write, "Memory Leak Summary\n"); fprintf(fp_write, "-----------------------------------\n"); // 遍历所有未释放的记录,写入文件 for (leak_info = ptr_start; leak_info != NULL; leak_info = leak_info->next) { fprintf(fp_write, "address : %p\n", leak_info->mem_info.address); fprintf(fp_write, "size : %d bytes\n", leak_info->mem_info.size); fprintf(fp_write, "file : %s\n", leak_info->mem_info.file_name); fprintf(fp_write, "line : %d\n", leak_info->mem_info.line); fprintf(fp_write, "-----------------------------------\n"); } fclose(fp_write); // 关闭输出文件 } clear(); // 清空链表,释放资源 } void dump_mem_leak(void) { MEM_LEAK *leak_info; fprintf(stderr, "Memory Leak Snapshot\n"); fprintf(stderr, "-----------------------------------\n"); for (leak_info = ptr_start; leak_info != NULL; leak_info = leak_info->next) { fprintf(stderr, "address : %p\n", leak_info->mem_info.address); fprintf(stderr, "size : %d bytes\n", leak_info->mem_info.size); fprintf(stderr, "file : %s\n", leak_info->mem_info.file_name); fprintf(stderr, "line : %d\n", leak_info->mem_info.line); fprintf(stderr, "-----------------------------------\n"); } }