2、 调用接口和数据结构
内存泄漏检测动态链接库提供的头文件resleak.h定义了所申请内存块的相关信息结构:
typedef struct leak_struct leak_t;
struct leak_struct{
void* p; //要跟踪的指针
char* callstack[MAX_LEVEL]; //堆栈跟踪信息,MAX_LEVEL宏定义为10
int level; //堆栈深度
char time[128]; //内存块申请时间
unsigned int size; //内存块申请大小
unsigned int thrdid; //当前线程ID
int type; //申请方式,区分os_malloc和mem_malloc
int nChanged; //linux下用于堆栈跟踪信息转换的标志
struct leak_struct* next;
};
struct leak_struct{
void* p; //要跟踪的指针
char* callstack[MAX_LEVEL]; //堆栈跟踪信息,MAX_LEVEL宏定义为10
int level; //堆栈深度
char time[128]; //内存块申请时间
unsigned int size; //内存块申请大小
unsigned int thrdid; //当前线程ID
int type; //申请方式,区分os_malloc和mem_malloc
int nChanged; //linux下用于堆栈跟踪信息转换的标志
struct leak_struct* next;
};
该数据结构定义的变量用于保存达梦服务器申请内存时的相关信息,并用一个单向链表串联起来。该单向链表的起始长度为1,在调用初始化接口leak_init函数时创建了一个头结点,当达梦服务器申请新的内存时,则创建新的信息结点,插入到该链表中,而在达梦服务器释放内存时,则遍历该链表,寻找到对应的信息结点后,将其从该链表中删除。
头文件resleak.h中还申明了动态链接库的调用接口,如下:
1) 初始化函数接口:
leak_t*
leak_init();
leak_init();
接口功能:创建信息结点链表的头结点,和多线程互斥变量,并返回头结点地址。
2) 退出清理函数接口
void
leak_deinit(leak_t* head);
leak_deinit(leak_t* head);
接口功能:释放链表中所有信息结点和互斥变量
3) 添加信息结点
BOOL
add_leak_point(leak_t* head, void* p,unsigned int nSize,int nType);
add_leak_point(leak_t* head, void* p,unsigned int nSize,int nType);
接口功能:申请内存成功后,向信息结点链表中添加该内存块相关的信息结点。
4) 删除信息结点
BOOL
release_leak_point(leak_t* head, void* p,int nType);
release_leak_point(leak_t* head, void* p,int nType);
接口功能:释放内存成功后,在信息结点链表中删除该内存块相关的信息结点。
5) 保存未释放信息结点的堆栈信息到文件中
BOOL
write_leak_to_file(leak_t* head, char* filename);
write_leak_to_file(leak_t* head, char* filename);
接口功能:遍历信息结点链表,打印当前未释放的每一个内存块的堆栈跟踪信息。