📄 m_osip_port.c
字号:
/*
说明:有关内存泄露测试的代码,在进入整个程序之前void DebugMemoryBegin(void)一下,在程序出去之前void DebugMemoryEnd(void)一下
如:
#ifndef DBGMEM_TRACE
#define DBGMEM_TRACE
#endif
#include "m_osip_port.h"
int main(int argc, char **argv)
{
声明变量
DebugMemoryBegin();
执行语句
DebugMemoryEnd();
return 0;
}
记得在包含头文件m_osip_port.h之前要打开宏DEBUG_MEM, 不用
*/
#include <memory.h>
#include <pthread.h>
#include "m_osip_port.h"
#include "m_osip_list.h"
static pthread_mutex_t DebugMemorymutex;
static m_osip_list_t g_M_list;
static int M_log_t_size; //结构大小
#ifdef DBGMEM_SAVE2FILE
static FILE *fp_bt = stdout; //存放内存泄露信息的文件指针
#endif
/*
说明,每调用一次malloc分配一个M_log_t结构来记录分配内存块的信息, 可以记录在哪个文件哪一行
哪个函数中申请了多少内存,指针是多少,但是缺陷在于无法显示调用堆栈
*/
M_log_t *M_log_tConstruct(void *p, char *file, char *func, unsigned short line, int size)
{
M_log_t *m_log;
if((m_log = (M_log_t *)malloc(sizeof(M_log_t))) == NULL)
{
printf("fatal error in file(%s) line(%d): malloc error!\n", __FILE__, __LINE__);
return NULL;
}
memset(m_log, 0, sizeof(M_log_t));
m_log->p = p;
if(strlen(file) > sizeof(m_log->file)-1)
{
return NULL;
}
strcpy(m_log->file, file);
if(strlen(func) > sizeof(m_log->func)-1)
{
return NULL;
}
strcpy(m_log->func, func);
m_log->line = line;
m_log->size = size;
//如果需要跟踪堆栈并将堆栈信息打印到终端
#if defined(DBGMEM_TRACE)
memset(&m_log->traceinfo, 0, sizeof(TraceInfo_t));
{
void *array[BTDEPTH];
m_log->traceinfo.size = backtrace (array, BTDEPTH);
m_log->traceinfo.strings = backtrace_symbols (array, m_log->traceinfo.size );
}
#endif
#ifdef DBGMEM_SAVE2FILE
FILE *fp;
#endif
return m_log;
}
/*
M_log_t结构的析构函数
*/
void *M_log_tDestruct(M_log_t *p)
{
void *ret = NULL;
if(p==NULL)
return NULL;
printf("memory leak(0x%x):file(%s) line(%d) function(%s) size(%d)\n", p->p, p->file, p->line, p->func, p->size);
#ifdef DBGMEM_TRACE
{
int i;
for (i = 2; i < p->traceinfo.size; i++) //i=2开始是为了显示起来更方便
printf ("%s\n", p->traceinfo.strings[i]);
free ( p->traceinfo.strings);
printf("\n");
}
#endif
ret = p->p;
free(p);
p=NULL;
return ret;
}
/*
初始化一下记录内存分配链表的指针
*/
#ifdef DBGMEM_SAVE2FILE
void DebugMemoryBegin(char *fname)
#else
void DebugMemoryBegin(void)
#endif
{
/* 用默认属性初始化一个互斥锁对象*/
pthread_mutex_init (&DebugMemorymutex,NULL);
pthread_mutex_lock (&DebugMemorymutex);
m_osip_list_init (&g_M_list);
M_log_t_size = sizeof(M_log_t);
#ifdef DBGMEM_SAVE2FILE
fp_bt = fopen(fname, "w+");
if(fp_bt == NULL)
{
fprintf(stderr, "cannot open file %s, the informations are redirected to stdout\n", fname);
fp_bt = stdout;
}
#endif
pthread_mutex_unlock(&DebugMemorymutex);
}
/*
说明:处理泄露的内存,也就是在整个程序执行过程中没有被释放掉的内存,释放他们并在终端打印出这些泄露的内存块信息
*/
void DebugMemoryEnd(void)
{
/* 锁定互斥锁*/
pthread_mutex_lock (&DebugMemorymutex);
m_osip_list_special_free (&g_M_list, M_log_tDestruct);
#ifdef DBGMEM_SAVE2FILE
fclose(fp_bt);
fp_bt = stdout;
#endif
/* 打开互斥锁*/
pthread_mutex_unlock(&DebugMemorymutex);
}
/*
This is a debug facility for detecting memory leaks.
I recommend to use external tools such as mpatrol
when possible. On some fancy platform, you may not
have any usefull tools: in this case, use this code!
*/
void *
_DebugMemory_malloc (size_t size, char *file, char *func, unsigned short line)
{
void *mem;
mem = malloc(size);
if (mem != NULL)
{
#ifdef DBGMEM_SAVE2FILE
fprintf(fp_bt, "memory leak(0x%x):file(%s) line(%d) function(%s) size(%d)\n", p->p, p->file, p->line, p->func, p->size);
#endif
M_log_t *plog = M_log_tConstruct(mem, file, func, line, size);
if(plog == NULL)
{
printf("M_log_t Construct error:file(%s) line(%d)\n",file,line);
return mem;
}
/* 锁定互斥锁*/
pthread_mutex_lock (&DebugMemorymutex);
m_osip_list_add (&g_M_list, plog, -1); //如果申请内存成功,记录内存信息并将其插入到链表末尾
/* 打开互斥锁*/
pthread_mutex_unlock(&DebugMemorymutex);
return mem;
}
return NULL;
}
void
_DebugMemory_free (void *ptr)
{
if(ptr == NULL)
return;
{//从g_M_list链表中删除相应内存块的信息
int pos = 0;
M_log_t *plog ;
/* 锁定互斥锁*/
pthread_mutex_lock (&DebugMemorymutex);
while ((!m_osip_list_eol (&g_M_list, pos)))
{
plog = ( M_log_t *)m_osip_list_get (&g_M_list, pos);
if(plog->p == ptr)
{
m_osip_list_remove (&g_M_list, pos);
free(plog); //删除M_log_t信息占用的内存
}
pos++;
}
/* 打开互斥锁*/
pthread_mutex_unlock(&DebugMemorymutex);
}
free(ptr); //删除内存块
ptr = NULL;
}
void *
_DebugMemory_realloc (void *ptr, size_t size, char *file, char *func, unsigned short line)
{
void *mem;
{//从g_M_list链表中删除相应内存块的信息
int pos = 0;
M_log_t *plog ;
/* 锁定互斥锁*/
pthread_mutex_lock (&DebugMemorymutex);
while ((!m_osip_list_eol (&g_M_list, pos)))
{
plog = ( M_log_t *)m_osip_list_get (&g_M_list, pos);
if(plog->p == ptr)
{
m_osip_list_remove (&g_M_list, pos);
free(plog);
}
pos++;
}
/* 打开互斥锁*/
pthread_mutex_unlock(&DebugMemorymutex);
}
mem = realloc(ptr, size);
if (mem != NULL)
{
M_log_t *plog = M_log_tConstruct(mem, file, func, line, size);
if(plog == NULL)
{
printf("M_log_t Construct error:file(%s) line(%d)\n",file,line);
return mem;
}
/* 锁定互斥锁*/
pthread_mutex_lock (&DebugMemorymutex);
m_osip_list_add (&g_M_list, plog, -1); //如果申请内存成功,记录内存信息并将其插入到链表末尾
/* 打开互斥锁*/
pthread_mutex_unlock(&DebugMemorymutex);
return mem;
}
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -