[经验之谈]C/C++的一个内存分配记录模块

来源:互联网 发布:淘宝店铺金牌卖家 退货 编辑:程序博客网 时间:2024/05/23 12:09

        在C/C++编程中,让无数开发者头痛的事情莫过于在程序中使用指针了。所以很多的人致力于寻找一种高效的垃圾自动回收机制来让天下的程序员从此不再烦恼此事。这当然是令人高兴的事,但是真正做起来却是各种的不如人意。我倒是认为“堵不如疏”。既然不能从语言机制上根本的解决这个问题,还不如想办法让程序员在开发过程中就能清晰的看到内存分配和释放情况。(当然了,为了在项目中彻底的避免因为各种原因导致的资源为被释放,实现一个垃圾回收机制也是非常有必要的。)所以有了下面的一个内存分配记录模块。

        这个小模块采用了双向链表来记录软件内的内存分配列表,当然可以使用更高效的哈希表来实现,但是如果软件内资源严格的控制其生命周期,这个链表想来规模不会很大,而且这个链表也仅仅是设计在DEBUG模式下使用的,即使有性能损失也是可以接受的。

// PtrManager.h


#ifndef __PTR_MANAGER_H__
#define __PTR_MANAGER_H__

#ifdef __cplusplus
extern "C"{
#endif

#ifndef MAX_PATH
#define MAX_PATH 260
#endif

#ifndef MAX_FUNC
#define MAX_FUNC 255
#endif

// 定义指针的信息结构
typedef struct _ptr_body
{
void* ptr; // 指针地址
char type[8]; // 指针类型
char func[MAX_FUNC]; // 所在函数
long line; // 所在行
char file[MAX_PATH]; // 所在文件
}ptr_body;

// 定义链表的节点
typedef struct _ptr_node
{
struct _ptr_node* prev; // 前一个节点
struct _ptr_node* next; // 后一个节点
struct _ptr_body* body; // 指针信息节点
}ptr_node;

// 定义链表的结构
typedef struct _ptr_list
{
ptr_node* begin; // 链表头
ptr_node* end; // 链表尾
int size; // 链表大小
}ptr_list;

// 创建一个指针链表
ptr_list* create_ptr_list();
// 删除一个指针链表
void destory_ptr_list(ptr_list** list);

// 添加一个指针信息
ptr_node* add_ptr_body(void* ptr, char* type, char* func, long line, char* file, ptr_list* list);
// 删除一个指针信息
bool remove_ptr_body(void* ptr, ptr_list* list);

// 打印链表信息
void print_ptr_list(ptr_list* list);

// 新增一个指针
#define PTR_MANAGER_NEW(_PTR, list) add_ptr_body(_PTR, "new", __FUNCTION__, __LINE__ - 1, __FILE__, list);
#define PTR_MANAGER_MALLOC(_PTR, list) add_ptr_body(_PTR, "malloc", __FUNCTION__, __LINE__ - 1, __FILE__, list);
#define PTR_MANAGER_REALLOC(_PTR, list) add_ptr_body(_PTR, "realloc", __FUNCTION__, __LINE__ - 1, __FILE__, list);

// 删除一个指针
#define PTR_MANAGER_FREE(_PTR, list) remove_ptr_body(_PTR, list);
#define PTR_MANAGER_DELETE(_PTR, list) remove_ptr_body(_PTR, list);

#ifdef __cplusplus
}
#endif

#endif /*__PTR_MANAGER_H__*/


//
// PtrManager.cpp
// Author:lvan100 Date:2012/5/15
// Email:lvan100@yeah.net
//

#include "PtrManager.h"
#include <malloc.h>
#include <string.h>
#include <stdio.h>

// 创建一个指针信息结构
static ptr_body* create_ptr_body()
{
ptr_body* body = (ptr_body*)malloc(sizeof(ptr_body));

if (body != NULL)
{
memset(body, 0, sizeof(ptr_body));
}

return body;
}

// 删除一个指针信息结构
static void destory_ptr_body(ptr_body** body)
{
if (body != NULL && *body != NULL)
{
free(*body);
*body = NULL;
}
}

// 创建一个节点
static ptr_node* create_ptr_node()
{
ptr_node* node = (ptr_node*)malloc(sizeof(ptr_node));

if (node != NULL)
{
memset(node, 0, sizeof(ptr_node));
}

return node;
}

// 删除一个节点
static void destory_ptr_node(ptr_node** node)
{
if (node != NULL && *node != NULL)
{
free(*node);
*node = NULL;
}
}

// 创建一个指针链表
ptr_list* create_ptr_list()
{
ptr_list* list = (ptr_list*)malloc(sizeof(ptr_list));

if (list != NULL)
{
memset(list, 0, sizeof(ptr_list));
}

return list;
}

// 删除一个指针链表
void destory_ptr_list(ptr_list** list)
{
if (list != NULL && *list != NULL)
{
free(*list);
*list = NULL;
}
}

// 添加一个指针信息
static ptr_node* add_ptr_body(ptr_body* body, ptr_list* list)
{
if (body == NULL || list == NULL)
{
return NULL;
}

ptr_node* node = create_ptr_node();
if (node == NULL)
{
return NULL;
}

node->next = NULL; // 空节点
node->body = body; // 指向指针信息

if (list->begin == NULL)
{
list->begin = node;
node->prev = NULL;
}
else
{
list->end->next = node;
node->prev = list->end; // 链表的尾节点
}

list->end = node; // 尾节点指向新增节点
list->size += 1; // 链表大小增1

return list->end;
}

// 添加一个指针信息
ptr_node* add_ptr_body(void* ptr, char* type, char* func, long line, char* file, ptr_list* list)
{
if (ptr == NULL)
{
return NULL;
}

ptr_body* body = create_ptr_body();
if (body != NULL)
{
body->ptr = ptr;
strncpy_s(body->type, 8, type, strlen(type));
strncpy_s(body->func, MAX_FUNC, func, strlen(func));
body->line = line;
strncpy_s(body->file, MAX_PATH, file, strlen(file));
}

return add_ptr_body(body, list);
}

// 删除一个指针信息
bool remove_ptr_body(void* ptr, ptr_list* list)
{
if (ptr == NULL || list == NULL)
{
return false;
}

ptr_body* body = NULL;
ptr_node* node = list->begin;

while (node != NULL)
{
body = node->body;
if ((body != NULL) && (body->ptr == ptr))
{
// 如果找到相同的指针信息

if (node->prev == NULL)
{
// 如果是首节点
list->begin = node->next;
list->end = node->next;

if (node->next != NULL)
{
node->next->prev = NULL;
}
}
else
{
// 如果不是首节点

if (node->prev != NULL)
{
node->prev->next = node->next;
}

if (node->next != NULL)
{
node->next->prev = node->prev;
}

if (list->end == node)
{
list->end = node->prev;
}
}

destory_ptr_node(&node);
destory_ptr_body(&body);

list->size -= 1; // 链表大小自减1

break;
}

node = node->next;
}

if (list->size == 0)
{
list->begin = list->end = NULL;
}

return true;
}

// 打印链表信息
void print_ptr_list(ptr_list* list)
{
printf("A detailed list of the memory not released:\n");

ptr_body* body = NULL;
ptr_node* node = list->begin;

while(node != NULL)
{
body = node->body;
if (body != NULL)
{
printf("Addr:%x\tType:%s\tLine:%ld\tFunc:%s\tFile:%s\n",
body->ptr, body->type, body->line, body->func, body->file);
}

node = node->next;
}
}

// int _tmain(int argc, _TCHAR* argv[])
// {
// ptr_list* list = create_ptr_list();
// if (list != NULL)
// {
// char* pnew = new char[10];
// PTR_MANAGER_NEW(pnew, list);
//
// char* pnew2 = new char[10];
// PTR_MANAGER_NEW(pnew2, list);
//
// char* pmalloc = (char*)malloc(10);
// PTR_MANAGER_MALLOC(pmalloc, list);
//
// char* prealloc = (char*)realloc(pmalloc, 10);
// PTR_MANAGER_REALLOC(prealloc, list);
//
// print_ptr_list(list);
//
// // test sample.
// // 1.remove header.
// // 2.remove tail.
// // 3.remove middle.
// delete []pnew;
// PTR_MANAGER_DELETE(pnew, list);
// delete []pnew2;
// PTR_MANAGER_DELETE(pnew2, list);
// free(pmalloc);
// PTR_MANAGER_FREE(pmalloc, list);
// // free(prealloc);
// //PTR_MANAGER_FREE(prealloc, list);
//
//
// print_ptr_list(list);
// }
//
// destory_ptr_list(&list);
//
// return 0;
// }


原创粉丝点击