线上系统发现虚拟内存在不断的涨,出现内存泄露如何解;
1、内存泄露为什么不好处理;
1)虚拟内存在涨的时候,我们不确定是程序的需要还是内存泄漏;
2)不知道到底是哪行代码导致内存泄漏;
内存泄漏产生的原因无非是malloc/new和free/delete调用不匹配;
2、如何判断内存泄漏,哪个地方的代码实现导致内存泄漏;内存泄漏检测;
1)通过mtrace检测内存泄漏;运行代码后通过mem.txt日志查看内存泄漏情况;对于线上系统是需要重启的,如果不重启可以通过热更新,在.conf文件中加入mtrace;
运行上图程序得到mem.txt文件如下,通过+和-的匹配情况判断是否有内存泄漏;
然后通过addr2line命令就可以查看是在哪里出现了内存泄漏;
2)宏定义检测内存泄漏;
宏定义检测的优缺点:只适合在单文件中使用;
对于线上系统,通过热更新检测;
3)通过hook方式检测内存泄漏;
typedef void *(*malloc_t)(size_t size);
typedef void (*free_t)(void *ptr);
malloc_t malloc_f = NULL;
free_t free_f = NULL;
int enable_malloc_hook = 1;
int enable_free_hook = 1;
void *malloc(size_t size) {
if(enable_malloc_hook)
{
enable_malloc_hook= 0;
void *p = malloc_f(size);
void * caller = __builten_return address(0);
char buff[128];
sprintf(buff, "./mem/%p.mem", p);
FILE *fp = fopen(buff,"w");
fprintf(fp,"[+]%s :%d, addr: %p,size: %ld\n"FILE_,_LINE__, p,size);
fflush(fp);
enable malloc_hook = 1;
}
else
{
p = malloc_f(size);
}
return p;
}
void free(void *ptr) {
if(enable_free_hook)
{
enable_free_hook = 0;
char buff[128] = (0};
sprintf(buff,"./mem/%p.mem", p);
free_f(ptr);
enable free hook = 1;
}
}
static void init_hook(void) {
if (malloc_f == NULL) {
malloc_f = (malloc_t)dlsym(RTLD_NEXT, "malloc");
}
if (free_f == NULL) {
free_f = (free_t)dlsym(RTLD_NEXT, "free");
}
}
int main() {
init_hook();
void *p1 = malloc(10);
void *p2 = malloc(15);
void *p3 = malloc(20);
free(p2);
free(p3);
}
4)__libc_malloc();接口,malloc底层调用的是该接口;思路和hook是一样的;
5)老版本接口,是被攻击的很重要的点,即__malloc_hook,是一种指针的方式;系统提供了一个指针,每一次调用malloc函数的时候,底层会调用到__malloc_hook指针,这个指针是固定的值;这是linux本身提供的hook的机制;这种方式慎用,因为它已经是已被遗弃的老的接口;