C++内存泄漏的检测与实现详细流程

目录
  • 内存泄漏
  • 带来的问题
  • 难点
  • hook实现泄漏判断与追踪(malloc和free重载)
  • 宏定义实现hook

内存泄漏

malloc/new 调用在堆上分配的内存却没有相应的free/delete;

带来的问题

会逐渐吃掉虚拟内存

难点

如何判断是否内存泄漏

  1. (最毛糙)可以使用+1和-1,即当调用分配内存变量+1,释放内存时候,变量-1,进程退出输出的count=0,进程内存没有泄漏,否则有泄漏;
  2. 线上版本,做一个配置文件,设置是否存在内存泄漏的一个标志位,平时肉眼观察不出的内存泄漏,在长时间的运行积攒下,肯定会逐渐变大,然后当可以观察出有内存泄漏了,就将标志位置位1;进行热更新,释放相应的泄漏处理(如 hook);

如何判断在代码中哪里泄漏

  • 当已经怀疑有泄漏:使用简单的mtrace直接检查代码也是一个简单的操作。
  • hook实现泄漏判断与追踪:实现本地检查或者在线的全局实时检查(线上版本,写一个conf配置文件,热更新是否使用hook)
  • 宏定义实现 hook: 实现单个文件检查
  • 调用malloc的时候,自己构建一个内存池(慢慢合成),每次释放的时候,从池中删除。最终在池中的就是泄露的;

hook实现泄漏判断与追踪(malloc和free重载)

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#define MEM_CONTENT_LEN 128
typedef void *(*malloc_t)(size_t size);
malloc_t malloc_f = NULL;
typedef void(*free_t)(void *P);
free_t free_f;
int enable_malloc_hook = 1;
int enable_free_hook = 1;
void *malloc(size_t size){
    if (enable_malloc_hook)
    {
        enable_malloc_hook = 0;         //防止递归;不这么设计会发生循环调用  ,printf也会调用malloc  直接打印观察是否泄漏
        void *p = malloc_f(size);
        // printf("malloc\n");
        /*
        参数:
           0:当前函数在哪调用:  返回==f()-->malloc
           1: a()-->f()-->malloc
           2: a()-->b()-->f()-->malloc
        */
        void *caller = __builtin_return_address(0);
        char buff[MEM_CONTENT_LEN] = {0}; //具体是否泄漏,何处泄漏,打印到文件中
        sprintf(buff,"./mem/%p.mem",p);
        FILE *fp = fopen(buff,"w");
        fprintf(fp,"[+%p]malloc --> addr: %p,size: %lu\n",caller,p,size);
        fflush(fp);
        enable_malloc_hook = 1;
        return p;
    }
    else{
        return malloc_f(size);
    }
}
void free(void *p){
    // printf("free\n");
    if (enable_free_hook)
    {
        enable_free_hook = 0;
        char buff[MEM_CONTENT_LEN] = {0}; //具体是否泄漏,何处泄漏
        sprintf(buff,"./mem/%p.mem",p);
        if (unlink(buff) <0)
        {
            printf("double free:%p\n",p);
        }
        enable_free_hook= 1;
    }else{
        free_f(p);
    }
}
static int init_hook(){
    malloc_f = dlsym(RTLD_NEXT,"malloc");
    free_f = dlsym(RTLD_NEXT,"free");
}
int main(){
    init_hook(); // hook调用
    void *p = malloc(10);
    free(p);
    void *p1 = malloc(20);
    void *p2 = malloc(30);
    free(p1);
}

gcc -o hook hook.c -ldl  #编译
mkdir  mem  #存储文件
./hook   #进行检查,若mem中生成了文件,则说明出了内存泄漏的问题
cat mem/0x55a3d3e666c0.mem  # 具体泄露:[+0x55a3d381a59e]malloc --> addr: 0x55a3d3e666c0,size: 30

addr2line -fe ./hook -a 0x55a3d381a59e#检查具体泄露的出现代码地址

宏定义实现hook

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#define MEM_CONTENT_LEN 128
void *malloc_hook(size_t size,const char* file, int line){
    void *p = malloc(size);
    char buff[MEM_CONTENT_LEN] = {0}; //具体是否泄漏,何处泄漏,打印到文件中
    sprintf(buff,"./mem/%p.mem",p);
    FILE *fp = fopen(buff,"w");
    fprintf(fp,"[+%s:%d]malloc --> addr: %p,size: %lu\n",file,line,p,size);
    fflush(fp);
    return p;
}
void* free_hook(void *p,const char* file,int line)
{
    char buff[MEM_CONTENT_LEN] = {0}; //具体是否泄漏,何处泄漏
    sprintf(buff,"./mem/%p.mem",p);
    if (unlink(buff) <0)
    {
        printf("double free:%p\n",p);
    }
    free(p);
}
//如果宏定义放在函数实现前面,会出现循环调用
#define malloc(size)        malloc_hook(size,__FILE__,__LINE__)
#define free(p)     free_hook(p,__FILE__,__LINE__)
int main(){
    void *p = malloc(10);
    free(p);
    void *p1 = malloc(20);
    void *p2 = malloc(30);
    free(p1);
}

其中[+hook_def.c:39]说明了文件中的多少行出了问题;

到此这篇关于C++内存泄漏的检测与实现详细流程的文章就介绍到这了,更多相关C++内存泄漏内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++中关于Crt的内存泄漏检测的分析介绍

    尽管这个概念已经让人说滥了 ,还是想简单记录一下, 以备以后查询. 复制代码 代码如下: #ifdef _DEBUG#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)#else#define DEBUG_CLIENTBLOCK#endif#define _CRTDBG_MAP_ALLOC#include <crtdbg.h>#ifdef _DEBUG#define new DEBUG_CLIENTBLOCK#e

  • 详谈C++的内存泄漏问题

    1)有多少new就有多少delete.而且配对的new与delete要尽量在一个函数中.如果子函数中需要返回的数据是通过new来创建的,我的处理方式一般是在需要调用这个函数的位置将对应的数据规模创建好,并且通过指针或是引用传递到子函数中. 2)本人比较粗心大意,又一次在编码的过程中 竟然将delete语句放在了return语句的后面,导致程序运行的过程中会因内存不足二崩溃.检查了不下20遍才检查出来,真是哭的心情都有了.希望大家以我为戒,一定把return语句放在函数的最后面,估计也就我一个人犯

  • C++之内存泄漏排查详解

    目录 一 .经验排查 二 .使用Visual Leak Detector for Visual C++ 2.1 Visual Leak Detector for Visual C++简介 2.2 Visual Leak Detector源码获取编译 2.2.1 源码获取,相关git地址 2.2.2 发布版本获取 2.2.3 进行编译 2.2.4 自带gtest工程测试 2.3 如何测试自己的项目呢 2.3.1 配置工程 2.3.2 编写简单的测试用例 2.3.3 检测结果如图 三.总结 一 .经

  • C++程序检测内存泄漏的方法分享

    一.前言 在Linux平台上有valgrind可以非常方便的帮助我们定位内存泄漏,因为Linux在开发领域的使用场景大多是跑服务器,再加上它的开源属性,相对而言,处理问题容易形成"统一"的标准.而在Windows平台,服务器和客户端开发人员惯用的调试方法有很大不同.下面结合我的实际经验,整理下常见定位内存泄漏的方法. 注意:我们的分析前提是Release版本,因为在Debug环境下,通过VLD这个库或者CRT库本身的内存泄漏检测函数能够分析出内存泄漏,相对而言比较简单.而服务器有很多问

  • 如何通过wrap malloc定位C/C++的内存泄漏问题

    前言 用C/C++开发的程序执行效率很高,但却经常受到内存泄漏的困扰.本文提供一种通过wrap malloc查找memory leak的思路,依靠这个方法,笔者紧急解决了内存泄漏问题,避免项目流血上大促,该方法在日后工作中大放光彩,发现了项目中大量沉疴已久的内存泄漏问题. 什么是内存泄漏? 动态申请的内存丢失引用,造成没有办法回收它(我知道杠jing要说进程退出前系统会统一回收),这便是内存泄漏. Java等编程语言会自动管理内存回收,而C/C++需要显式的释放,有很多手段可以避免内存泄漏,比如

  • C++ 内存泄漏调试方式

    C++和其他高级语言不同,需要自行管理内存,项目大\调用多,容易内存泄漏.内存申请释放使用malloc/free和new delete两种方式. 当内存报错弹出一个陌生的地址,我一脸懵逼,不清楚是哪个地方出的错,特别是程序退出的时候报错更不好定位.可以使用第三方工具来定位解决,也可以自己想办法解决. 我在做神经网络训练的时候碰到一个的BUG,发送完训练图片之后直接提示使用了非法内存. HEAP[Test.exe]: HEAP: Free Heap block 0000015E950E4A60 m

  • C++内存泄漏及检测工具详解

    首先我们需要知道程序有没有内存泄露,然后定位到底是哪行代码出现内存泄露了,这样才能将其修复. 最简单的方法当然是借助于专业的检测工具,比较有名如BoundsCheck,功能非常强大,相信做C++开发的人都离不开它.此外就是不使用任何工具,而是自己来实现对内存泄露的监控,分如下两种情况: 一. 在 MFC 中检测内存泄漏 假如是用MFC的程序的话,很简单.默认的就有内存泄露检测的功能. 我们用VS2005生成了一个MFC的对话框的程序,发现他可以自动的检测内存泄露.不用我们做任何特殊的操作. 仔细

  • c++ 排查内存泄漏的妙招

    前言 对于c++而言,如何查找内存泄漏是程序员亘古不变的话题:解决之道可谓花样繁多.因为最近要用到QT写程序,摆在我面前的第一个重要问题是内存防泄漏.如果能找到一个简单而行之有效的方法,对后续开发大有裨益.久思终得诀窍,本文就详细介绍我对此问题的应对之策.(文末符完整代码) 如何判断内存有泄漏 内存分配和释放对应的操作是new.delete.如何判断内存是否释放干净?其实判断起来非常简单:一个独立的模块整个生存周期内new的个数和delete的个数相等.用伪代码标示如下: int newCoun

  • C++内存泄漏的检测与实现详细流程

    目录 内存泄漏 带来的问题 难点 hook实现泄漏判断与追踪(malloc和free重载) 宏定义实现hook 内存泄漏 malloc/new 调用在堆上分配的内存却没有相应的free/delete: 带来的问题 会逐渐吃掉虚拟内存 难点 如何判断是否内存泄漏 (最毛糙)可以使用+1和-1,即当调用分配内存变量+1,释放内存时候,变量-1,进程退出输出的count=0,进程内存没有泄漏,否则有泄漏: 线上版本,做一个配置文件,设置是否存在内存泄漏的一个标志位,平时肉眼观察不出的内存泄漏,在长时间

  • IOS内存泄漏检查方法及重写MLeakFinder

    对于iOS开发来讲,内存泄漏的问题,已经是老生常谈的话题.在日常的面试中经常会提到这些问题.我们日常的开发过程中进行内存泄漏的检测,一般是使用instrument工具中的Leaks/Allocation来进行排查,网络上也有比较高效又好用的内存泄漏检测工具,MLeakFinder. MLeakFinder-原理 首先看UIViewController,当一个UIViewController被pop或dismiss的时候,这个VC包括在这个VC上的View,或者子View都会很快的被释放.所以我们

  • 排查Java应用内存泄漏问题的步骤

    什么是内存泄漏 内存泄漏是指java应用的堆内存使用率持续升高,直至内存溢出. 内存泄漏的的原因可能有多种 分配给应用程序的内存本身过小.而应用的业务代码,确实需要生成大量的对象 代码bug,某些需要被回收的对象,由于代码bug,却持续的被引用,导致java虚拟机无法回收这些对象.从而撑爆内存 无论哪种内存泄露,我们的解决方法都是要定位到具体是什么对象,占用了大量内存,从而方便我们基于此进行代码分析,debug,找出代码问题. 而能够帮助我们实现这一目的的方式就是获取java应用的内存 dump

  • Android Handler内存泄漏原因及解决方案

    目录: 1.须知: 主线程Looper生命周期和Activity的生命周期一致. 非静态内部类,或者匿名内部类.默认持有外部类引用. 2.原因: Handler造成内存泄露的原因.非静态内部类,或者匿名内部类.使得Handler默认持有外部类的引用.在Activity销毁时,由于Handler可能有未执行完/正在执行的Message.导致Handler持有Activity的引用.进而导致GC无法回收Activity. 3.可能造成内存泄漏 匿名内部类: //匿名内部类 Handler handl

  • 详解Android内存泄漏检测与MAT使用

    内存泄漏基本概念 内存检测这部分,相关的知识有JVM虚拟机垃圾收集机制,类加载机制,内存模型等.编写没有内存泄漏的程序,对提高程序稳定性,提高用户体验具有重要的意义.因此,学习Java利用java编写程序的时候,要特别注意内存泄漏相关的问题.虽然JVM提供了自动垃圾回收机制,但是还是有很多情况会导致内存泄漏. 内存泄漏主要原因就是一个生命周期长的对象,持有了一个生命周期短的对象的引用.这样,会导致短的对象在该回收时候无法被回收.Android中比较典型的有:1.静态变量持有Activity的co

  • Tomcat 检测内存泄漏实例详解

     Tomcat如何检测内存泄漏 一般情况下,如果我们重启web应用是通过重启tomcat的话,则不存在内存泄漏问题.但如果不重启tomcat而对web应用进行重加载则可能会导致内存泄漏,因为重加载后有可能会导致原来的某些内存无法让GC回收,例如web应用使用了JDBC,驱动会进行注册,当web应用停止时没有反注册就会导致内存泄漏. 看看是什么原因导致tomcat内存泄漏的.这个要从热部署开始说起,因为tomcat提供了不必重启容器而只需重启web应用以达到热部署的功能,其实现是通过定义一个Web

  • Linux内存泄漏检测shell脚本

    本文实例为大家分享了Linux内存泄漏检测的shell脚本,供大家参考,具体内容如下 #!/bin/sh if [ $# -ne 1 ]; then echo "Usage: `basename $0` process_name" exit 1 fi APPNAME=$1 PROC="`ps -ef | grep "$APPNAME" | grep -v "grep" | grep -v "awk" | grep -

  • Java中关于内存泄漏出现的原因汇总及如何避免内存泄漏(超详细版)

    Android 内存泄漏总结 内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题.内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收.最近自己阅读了大量相关的文档资料,打算做个 总结 沉淀下来跟大家一起分享和学习,也给自己一个警示,以后 coding 时怎么避免这些情况,提高应用的体验和质量. 我会从 java 内存泄漏的基础知识开始,并通过具体例子来说明 Android 引起内存泄漏的各种原因,以

随机推荐