C/C++内存泄漏检测方法
1. 内存泄漏
内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
2. 检测代码
使用链表记录每个malloc返回的指针,释放时从链表中查找并删除找到对应指针的节点。
最终输出链表,该链表记录了所有没有释放的动态内存。
#include#include #include #include #include <malloc.h> #include <string.h> #include #define output_file "leak_detector_report.txt" typedef struct { void* addr; //the memory address unsigned char file[128]; //the file of the memory alloc statement unsigned int line; //the line of the memory alloc statment unsigned int size; //the size of the memory alloced }addr_info; typedef struct addr_info_node{ addr_info info; struct addr_info_node *next; }addr_info_node, *addr_info_list; pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; addr_info_list g_head = NULL; void *malloc_detector(int size, unsigned char *file, unsigned int line) { void *ptr = malloc(size); if (NULL == ptr) { return NULL; } addr_info_node *node = (addr_info_node*)malloc(sizeof(addr_info_node)); if (NULL == node) { return NULL; } memset(node, 0, sizeof(addr_info_node)); node->info.addr = ptr; node->info.line = line; node->info.size = size; strncpy(node->info.file,file,127); node->next = NULL; pthread_mutex_lock(&g_mutex); if (NULL == g_head) { g_head = (addr_info_node*)malloc(sizeof(addr_info_node)); if (NULL == g_head) { free(node); return NULL; } memset(g_head, 0, sizeof(addr_info_node)); } addr_info_node *tail = g_head; while (NULL != tail->next) { tail = tail->next; } tail->next = node; pthread_mutex_unlock(&g_mutex); return ptr; } void free_detector(void *addr) { //Find and Delete the info which has the address==addr from Alloc_Info_List head /*we only detecte the memory-leak, not the wrong free-addr which not in the addr_info_list*/ pthread_mutex_lock(&g_mutex); addr_info_node *node = g_head; while (NULL != node->next) { if (node->next->info.addr == addr) { free(addr); node->next = node->next->next; break; } printf("2 file %s line %d,addr %p,size %d\n", node->info.file,node->info.line,node->info.addr,node->info.size); node = node->next; } pthread_mutex_unlock(&g_mutex); } void report_info() { FILE *fp_write=fopen(output_file,"w+"); if(!fp_write) { printf("can't open file\n"); return; } char info[sizeof(addr_info)+128]; pthread_mutex_lock(&g_mutex); addr_info_node *node = g_head->next; while (NULL != node) { sprintf(info,"memory leak:file %s line %d,addr %p,size %d\n", node->info.file,node->info.line,node->info.addr,node->info.size); fwrite(info,strlen(info)+1,1,fp_write); node = node->next; } fclose(fp_write); pthread_mutex_unlock(&g_mutex); } void thread1_malloc_free() { void *ptr = malloc_detector(100, __FILE__, __LINE__); ptr = malloc_detector(200, __FILE__, __LINE__); free_detector(ptr); ptr = malloc_detector(200, __FILE__, __LINE__); } void thread2_malloc_free() { void *ptr = malloc_detector(400, __FILE__, __LINE__); ptr = malloc_detector(800, __FILE__, __LINE__); free_detector(ptr); ptr = malloc_detector(1600, __FILE__, __LINE__); } int main() { pthread_t thread1, thread2; pthread_create(&thread1, NULL, (void *)&thread1_malloc_free, NULL); pthread_create(&thread2, NULL, (void *)&thread2_malloc_free, NULL); pthread_join(thread1, NULL); pthread_join(thread2, NULL); report_info(); }
运行输出
memory leak:file memory_detector.c line 115,addr 0x7f88c0000b60,size 100 memory leak:file memory_detector.c line 123,addr 0x7f88b8000b60,size 400 memory leak:file memory_detector.c line 118,addr 0x7f88c0001120,size 200 memory leak:file memory_detector.c line 126,addr 0x7f88b8001170,size 1600