使用c语言封装malloc和free函数,检测分配和释放释放匹配,并记录调用者文件名字、行数、申请和释放大小等
时间: 2024-02-03 10:04:40 浏览: 154
以下是一个简单的实现,使用了宏定义来封装malloc和free函数:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 用于记录调用者信息的结构体
typedef struct {
const char* file; // 文件名
int line; // 行号
} CallerInfo;
// 用于记录分配和释放信息的结构体
typedef struct {
size_t size; // 分配/释放的大小
CallerInfo caller; // 调用者信息
} AllocationInfo;
// 定义一个全局变量,用于存储分配和释放信息
AllocationInfo* g_allocation_info = NULL;
// 定义一个宏,用于记录调用者信息
#define CALLER_INFO (CallerInfo){__FILE__, __LINE__}
// 定义一个封装了malloc函数的宏,会记录分配的信息
#define my_malloc(size) ({ \
void* ptr = malloc(size); \
if (ptr) { \
AllocationInfo info = {size, CALLER_INFO}; \
g_allocation_info = realloc(g_allocation_info, sizeof(AllocationInfo) * (i + 1)); \
g_allocation_info[i++] = info; \
} \
ptr; \
})
// 定义一个封装了free函数的宏,会检测释放是否匹配,并记录释放的信息
#define my_free(ptr) ({ \
if (ptr) { \
for (int j = 0; j < i; j++) { \
if (g_allocation_info[j].caller.file && g_allocation_info[j].caller.line && g_allocation_info[j].size && g_allocation_info[j].caller.file == __FILE__ && g_allocation_info[j].caller.line == __LINE__) { \
if (ptr == (void*)g_allocation_info[j].caller.file) { \
memset(&g_allocation_info[j], 0, sizeof(AllocationInfo)); \
free(ptr); \
ptr = NULL; \
break; \
} \
} \
} \
} \
})
// 定义一个全局变量,用于记录分配和释放信息的个数
int i = 0;
int main() {
// 测试使用封装后的malloc和free函数
int* p = my_malloc(sizeof(int));
*p = 123;
printf("%d\n", *p);
my_free(p);
// 输出所有未释放的内存块信息
for (int j = 0; j < i; j++) {
if (g_allocation_info[j].caller.file && g_allocation_info[j].caller.line && g_allocation_info[j].size) {
printf("memory leak: %s:%d %zu bytes\n", g_allocation_info[j].caller.file, g_allocation_info[j].caller.line, g_allocation_info[j].size);
}
}
// 释放全局变量
free(g_allocation_info);
return 0;
}
```
这里使用了两个宏来封装malloc和free函数:my_malloc和my_free。其中,my_malloc会在分配内存时记录分配信息,而my_free会检测释放是否匹配,并记录释放信息。我们还定义了两个结构体:CallerInfo用于记录调用者信息,AllocationInfo用于记录分配和释放信息。最后,我们在main函数中测试了使用封装后的my_malloc和my_free函数,并输出了所有未释放的内存块信息。
阅读全文