⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m_osip_port.c

📁 一个在linux下跟踪内存泄露的小程序,一般在linux下可以用 mtrace valgrind来做,但是在嵌入式上,由于内存的限制,mtrace valgrind都显得束手无策
💻 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 + -