线上系统发现虚拟内存在不断的涨,出现内存泄露如何解;
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的机制;这种方式慎用,因为它已经是已被遗弃的老的接口;