最近做rtmp推流的时候由于使用了很多librtmp和其他代码,逻辑混乱导致功能虽然都实现了,但是出现了内存泄露的现象。其实不改也不会影响使用,因为吃的一点也不厉害,反复大量的启动关闭才会出现泄露,实际使用没有那么变态的操作。但谁让咱严谨呢。
首先上网查,无非那几个办法。但我们是嵌入式交叉编译,valgrind就别想了,因为连mtrace都没有!mtrace还是很好用的,就按其他博客写的那样去操作就行。设置环境变量,调用mtrace,linux系统自动去给你统计内存开销情况。到时候反汇编指针就OK了。
下面说说我的办法吧,其实大家也都是采用的这个办法,简单点说就是重定向内存开销接口。把malloc、calloc、realloc、strdup和free重定向成你自己写的接口。然后用一个写着内存大小接口等数据的数据结构链表来记录所有的申请还没有被销毁的内存。开一块内存加一个节点,free一块就从链表中删除。然后你想什么时候看看这个链表就把它写到文件里,自己去cat文件即可。
结果是美好的,一下子就找到了内存重开没释放的逻辑,然后分析修改代码,问题就解决了。为什么会出现这次的内存泄露呢,就是因为代码不熟悉,不全是我写的。虽然改完了,功能也都正常,但心里还是不放心,因为我暂时还无法完全掌控。下面我把代码贴出来,修改调试了很久,里面做了很多注释,独立性相当强,不和任何模块相关。可以说拿过去直接用就行。后面我会说使用方法。
//leak.h
#ifndef PROJECT_LEAK_H
#define PROJECT_LEAK_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "rtmp_client_protocol.h"
#ifdef LEAK_CHECK
void leak_free(void *_ptr,const char *_file,const char *_func, unsigned int _line);
void * leak_malloc(size_t _size,const char *_file,const char *_func, unsigned int _line);
void * leak_calloc(size_t nmemb, size_t size, const char *_file,const char *_func, unsigned int _line);
void * leak_realloc(void *ptr, size_t size, const char *_file,const char *_func, unsigned int _line);
char * leak_strdup(const char *_s, const char *_file,const char *_func, unsigned int _line);
# ifdef free
# undef free
# endif
# ifdef malloc
# undef malloc
# endif
# ifdef calloc
# undef calloc
# endif
# ifdef realloc
# undef realloc
# endif
# ifdef strdup
# undef strdup
# endif
#define free(p) leak_free(p, __FILE__, __FUNCTION__, __LINE__)
#define malloc(size) leak_malloc(size, __FILE__, __FUNCTION__, __LINE__)
#define calloc(n, size) leak_calloc(n, size, __FILE__, __FUNCTION__, __LINE__)
#define realloc(p, size) leak_realloc(p, size, __FILE__, __FUNCTION__, __LINE__)
#define strdup(s) leak_strdup(s, __FILE__, __FUNCTION__, __LINE__)
int leak_dbg_msg(char *_buf, int _size);
void leak_output(void);
#endif
#endif //PROJECT_LEAK_H
//leak.c
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
#define MAX_FUNC_INFO 32 /*the functions of per process memory leak number, 32 is enough*/
#define LEAK_VERIFY 0x20190121 /*just a random value to check memory point*/
#define MAX_MSG_LEN 4*1024 /*the file length, you can expand it as you want*/
#define LEAK_PATH "./leak_check" /*the path of the file which records the memory you forget*/
typedef struct {
char *file;
char *func;
int line;