一个简单的内存泄漏检测C工具
这个内存泄漏检测工具很简单,只能检测同一个模块,同一个线程中发送的内存泄漏,对于在编写代码过程中的代码调试有一定的帮助。如果要在集成测试或功能测试中检测内存泄漏,还需借助专门的工具。
1. 先取向malloc,free和calloc这几个标识符的定义:注意这一步非常重要,否则后面的malloc、free和calloc函数会和我们稍后在头文件中定义的宏冲突
// 取消malloc, calloc, free的宏定义#undef malloc#undef calloc#undef free
2. 定义保存内存信息的单向链表
/** * 定义链表节点,表示一个内存泄漏信息 */typedef struct _mem_node{ void *ptr; // 泄漏内存地址 size_t block; // 泄漏内存大小 size_t line; // 泄露发生的代码行 char *filename; // 泄漏发生的文件名 struct _mem_node *next; // 下一个节点指针} mem_node;// 定义指向头节点的指针mem_node *head = NULL;
3. 用于将节点加入单项链表的函数
/** * 产生一个节点并加入链表 * @param ptr 分配的内存地址 * @param block 分配的内存单元大小 * @param line 代码行号 * @param filename 文件名称 */static void mem_node_add(void *ptr, size_t block, size_t line, char *filename){ // 产生节点 mem_node *node = malloc(sizeof(mem_node)); node->ptr = ptr; node->block = block; node->line = line; node->filename = filename; node->next = NULL; // 加入链表头节点 if (head) { node->next = head; head = node; } else head = node;}
4. 从单项链表中删除节点的函数
/** * 从链表中删除一个节点 * @param ptr 分配的内存地址 */static void mem_node_remove(void *ptr){ // 判断头节点是否存在 if (head) { // 处理头节点 if (head->ptr == ptr) { // 获取头节点的下一个节点 mem_node *pn = head->next; // 删除头节点 free(head); // 令头节点指针指向下一个节点 head = pn; } else // 判断链表是否为空 { // 指向节点的指针 mem_node *pn = head->next; // 指向前一个节点的指针 mem_node *pc = head; // 遍历所有节点 while (pn) { // 获取指向下一个节点的指针 mem_node *pnext = pn->next; if (pn->ptr == ptr) { pc->next = pnext; // 删除当前节点 free(pn); } else pc = pc->next; pn = pnext; } } }}
5. 显示内存泄露信息报告
/** * 显示内存泄漏信息 */void show_block(){ if (head) { // 保存总内存泄漏数量 size_t total = 0; // 指向头节点的指针 mem_node *pn = head; // 输出标题 puts("/n/n-------------------------------内存泄漏报告------------------------------------/n"); // 遍历链表 while (pn) { mem_node *pnext = pn->next; // 处理文件名 char *pfile = pn->filename, *plast = pn->filename; while (*pfile) { // 找到/字符 if (*pfile == '//') plast = pfile + 1; // 获取/字符的位置 pfile++; } // 输出内存泄漏信息 printf("位置:%s(%d), 地址:%p(%dbyte)/n", plast, pn->line, pn->ptr, pn->block); // 累加内存泄漏总量 total += pn->block; // 删除链表节点 free(pn); // 指向下一个节点 pn = pnext; } printf("总计内存泄漏:%dbyte/n", total); }}
6. 定义调试用malloc函数
/** * 用于调试的malloc函数 * @param elem_size 分配内存大小 * @param filename 文件名称 * @param line 代码行号 */void *dbg_malloc(size_t elem_size, char *filename, size_t line){ void *ptr = malloc(elem_size); // 将分配内存的地址加入链表 mem_node_add(ptr, elem_size, line, filename); return ptr;}
7. 定义调试用的calloc函数
/** * 用于调试的calloc函数 * @param count 分配内存单元数量 * @param elem_size 每单元内存大小 * @param filename 文件名称 * @param line 代码行号 */void *dbg_calloc(size_t count, size_t elem_size, char *filename, size_t line){ void *ptr = calloc(count, elem_size); // 将分配内存的地址加入链表 mem_node_add(ptr, elem_size * count, line, filename); return ptr;}
8. 定义调试用的free函数
/** * 用于调试的free函数 * @param ptr 要释放的内存地址 */void dbg_free(void *ptr){ free(ptr); // 从链表中删除节点 mem_node_remove(ptr);}
上述代码应包含在一个C文件中(例如memcheck.c),完成上述步骤,就可以利用这一组函数来检测内存泄露了,需要定义如下头文件,该头文件应该被书写上述函数的C文件include:
#ifndef _MEM_CHECK_H#define _MEM_CHECK_H#include// instead of malloc#define malloc(s) dbg_malloc(s, __FILE__, __LINE__)// instead of calloc#define calloc(c, s) dbg_calloc(c, s, __FILE__, __LINE__)// instead of free#define free(p) dbg_free(p)/** * allocation memory */void *dbg_malloc(size_t elem_size, char *filename, size_t line);/** * allocation and zero memory */void *dbg_calloc(size_t count, size_t elem_size, char *filename, size_t line);/** * deallocate memory */void dbg_free(void *ptr);/** * show memory leake report */void show_block();#endif // _MEM_CHECK_H
使用的时候只需要包含上述头文件(例如命名为memcheck.h),并将上述C文件引入到项目中即可。测试代码如下:
#ifdef DEBUG#include "memcheck.h"#endifint main(){ int* p;#ifdef DEBUG atexit(show_block); // 在程序结束后显示内存泄漏报告#endif // DEBUG // 分配内存并不回收,显示内存泄漏报告 p = (int*)malloc(1000); return 0;}
>更多相关文章
- 09-29如何通过wrap malloc定位C/C++程序的内存泄漏
- 02-25打车软件大战升级,补贴还能维持多久?
- 12-23BMP文件右旋90度[c语言]
- 12-23寻找直方图中面积最大的矩形(C语言版)
- 12-23[ndk,2]ndk开发案例和错误处理
- 12-23[ndk,1]ndk开发,C语言入门讲解
- 12-23C语言连续存储实现队列机制
- 12-23Objective-c 数据类型
首页推荐
佛山市东联科技有限公司一直秉承“一切以用户价值为依归
- 01-11全球最受赞誉公司揭晓:苹果连续九年第一
- 12-09罗伯特·莫里斯:让黑客真正变黑
- 12-09谁闯入了中国网络?揭秘美国绝密黑客小组TA
- 12-09警示:iOS6 惊现“闪退”BUG
- 12-05亚马逊推出新一代基础模型 任意模态生成大模
- 12-05OpenAI拓展欧洲业务 将在苏黎世设立办公室
- 12-05微软质疑美国联邦贸易委员会泄露信息 督促其
- 12-05联交所取消宝宝树上市地位 宝宝树:不会对公
- 12-04企业微信致歉:文档打开异常已完成修复
相关文章
24小时热门资讯
24小时回复排行
热门推荐
最新资讯
操作系统
黑客防御