内存泄漏检测组件的实现

内存泄漏是在没有自动GC的编程语言里面,经常发生的一些问题。要实现一个内存泄露的检测组件,有两个需求:

  1. 能够检测出来内存泄漏
  2. 能够判断出来哪一个地方的申请没有释放(哪一行引起的泄漏)

方案1:借助mtrace

mtrace是一个Linux系统下的内存泄漏检测工具,它可以跟踪程序中的内存分配和释放操作,并记录每个内存块的分配和释放位置。通过分析mtrace的输出,我们可以找到内存泄漏的地方。

下面是一个简单的示例程序,演示如何使用mtrace来检测内存泄漏:

#include <stdio.h>
#include <stdlib.h>
#include <mcheck.h>

int main() {
    setenv("MALLOC_TRACE", "trace.log", 1);
    mtrace();
    int* p = malloc(sizeof(int));
    free(p);
    muntrace();
    return 0;
}

在这个程序中,我们使用了mcheck.h头文件中的mtracemuntrace函数来启用和禁用内存跟踪功能。在程序开始时,我们通过调用setenv函数设置环境变量MALLOC_TRACE,将内存跟踪日志输出到文件trace.log中。然后,我们调用mtrace函数启用内存跟踪。在程序结束时,我们调用muntrace函数禁用内存跟踪。

运行程序后,mtrace会记录程序中的内存分配和释放操作,并将跟踪日志输出到文件trace.log中。我们可以使用mtrace命令行工具来分析这个日志文件,找到内存泄漏的地方。例如,假设trace.log文件的内容如下:

Memory not freed:
-----------------
         Address     Size     Caller
0x0000000000602010     0x4  at /home/user/test.c:8

这个日志文件告诉我们,程序在文件test.c的第8行分配了一个4字节的内存块,但是没有释放它。通过查看日志文件中的Caller字段,我们可以找到这个内存块的分配位置。在这个例子中,我们可以看到,这个内存块是在test.c文件的第8行分配的。

需要注意的是,mtrace只能检测到使用mallocfree函数分配和释放的内存块,对于其他的内存分配和释放操作,mtrace可能无法正确地跟踪和记录。此外,mtrace会增加程序的运行时间和内存占用,因此在生产环境中应该谨慎使用。

方案2

实现自定义的内存分配和释放函数,它会在每次内存分配和释放时将分配和释放的地址、大小、文件名和行号等信息输出到一个以分配地址为名的文件中。这样可以方便地跟踪内存分配和释放的位置和大小,以便检测内存泄漏和其他内存相关的问题。

这个实现的原理是,在每次内存分配时,先调用系统的malloc函数分配内存,然后根据分配的地址生成一个文件名,并将分配的地址、大小、文件名和行号等信息输出到文件中。在每次内存释放时,先根据释放的地址生成文件名,然后从文件系统中删除对应的文件,并调用系统的free函数释放内存。

需要注意的是,这个实现并不是线程安全的,如果在多线程环境中使用,可能会出现竞争条件。此外,这个实现也会增加程序的运行时间和磁盘占用,因此做测试用就好。


void *_malloc(size_t size, char *filename, int line)
{
    void *p = malloc(size);
    // printf("[+]%s:%d, %p\n", filename, line, p);

    char buff[128] = {0};
    sprintf(buff,"./mem/%p.mem",p);

    FILE *fp = fopen(buff,"w");
    fprintf(fp,"[+]%s:%d, addr:%p, size:%ld\n",filename,line,p,size);

    fflush(fp);
    fclose(fp);

    return p;
}

void _free(void *p, char *filename, int line)
{
    char buff[128] = {0};
    sprintf(buff,"./mem/%p.mem",p);


    if(unlink(buff) < 0)
    {
        printf("double free: %p\n",p);
        return ;
    }

    return free(p);
}

#define malloc(size) _malloc(size, __FILE__, __LINE__)
#define free(size) _free(size, __FILE__, __LINE__)

方案3

这段代码在C语言中实现了对mallocfree函数的钩子(hook)。

malloc函数用于分配指定大小的内存块,free函数用于释放先前分配的内存块。

代码中定义了两个函数指针类型 malloc_tfree_t,分别代表了指向 mallocfree 函数的指针类型。

然后定义了两个全局变量 malloc_ffree_f,用于保存实际的 mallocfree 函数的地址。

接下来是两个整型变量 enable_malloc_hookenable_free_hook,用于控制是否启用钩子功能。

ConvertToELF 函数用于将传入的地址转换为 ELF(可执行和可链接格式)的地址。(这一步能让我们可以通过后面的addr2line找到泄露位置)

malloc 函数中,如果钩子功能被启用(enable_malloc_hook 为真),则会记录调用 malloc 的函数地址、分配的内存地址和大小,并将这些信息写入一个文件中。

free 函数中,如果钩子功能被启用(enable_free_hook 为真),则会删除之前记录的文件,并调用实际的 free 函数释放内存。

最后,init_hook 函数用于初始化钩子,通过 dlsym 函数获取实际的 mallocfree 函数的地址。

总的来说,这段代码通过钩子机制,在每次调用 mallocfree 函数时记录相关信息,并可以在分配和释放内存时执行额外的操作。

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 *ConvertToELF(void *addr)
{
    Dl_info info;
    struct link_map *link;

    dladdr1(addr,&info,(void**)&link,RTLD_DL_LINKMAP);

    return (void *)((size_t)addr - link->l_addr);


}

void *malloc(size_t size)
{
    void *p = NULL;

    if (enable_malloc_hook)
    {
        enable_malloc_hook = 0;
        // printf("malloc size: %ld\n", size);

        p = malloc_f(size);

        // 返回谁调用的这个谁所在地址
        void *caller = __builtin_return_address(0);

        char buff[128] = {0};
        sprintf(buff, "./mem/%p.mem", p);

        FILE *fp = fopen(buff, "w");

        fprintf(fp, "[+]%p,addr:%p,size:%ld\n", ConvertToELF(caller), p, size);

        fflush(fp);

        enable_malloc_hook = 1;

    }
    else
    {
        p = malloc_f(size);
    }

    return p;
}

void free(void *p)
{
    if (enable_free_hook)
    {
        enable_free_hook = 0;
        char buff[128] = {0};
        sprintf(buff, "./mem/%p.mem", p);

        if (unlink(buff) < 0)
        {
            printf("double free:%p\n", p);
            return;
        }
        free_f(p);

        enable_free_hook = 1;
    }
    else
    {
        free_f(p);
    }
    // retu/rn;
}

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");
    }
}

对于上面的方案,内存分配释放的信息被写入文件后,我们以方案3举例,打开文件可以看到如下信息在这里插入图片描述
然后我们借助addr2line工具,直接定位带泄漏位置,如下示例:
在这里插入图片描述
综上,我们即可找到内存泄露位置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/334055.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【GitHub项目推荐--名校课程资源】【转载】

先引用一段话&#xff0c;今天推荐的所有 GitHub 项目创立动机几乎都是这个。本文会盘点清华、北大、斯坦福、中国科学技术大学、上海交大等学校的课程资源。 01. 浙江大学课程共享计划 上图截屏中的话就是出自该项目&#xff0c;浙江大学搞了一个课程共享计划&#xff0c;其…

龙芯+RT-Thread+LVGL实战笔记(30)——电子琴演奏

【写在前面】正值期末,笔者工作繁忙,因此本系列教程的更新频率有所放缓,还望订阅本专栏的朋友理解,请勿催更。笔者在此也简要声明几点: 有些硬件模块笔者并没有,如LED点阵、压力传感模块、RFID模块等,因此这些模块的相关任务暂时无法给出经过验证的代码。其实,教程进行…

Mysql中的日志系统

文章目录 1. 慢查询日志&#xff08;Slow Query Log&#xff09;1.1 是否开启慢查询日志1.2 开启慢查询日志&#xff0c;设置时间阈值1.2.1 修改文件my.ini1.2.2 重启mysql后配置生效 1.3 查看慢查询日志1.3.1 直接用文本编辑器打开1.3.2 使用mysqldumpslow进行分析 2. InnoDB …

IaC基础设施即代码:Terraform 使用 dynamic动态内联块 创建docker资源

目录 一、实验 1.环境 2.Terraform查看版本 3.Linux主机安装Docker 4.Terraform使用本地编译&#xff08;In-house&#xff09;的Providers 5.Docker-CE 开启远程API 6. Linux主机拉取镜像 7.Terraform 使用 dynamic动态内联块 创建资源 二、问题 1.Terraform 计划资源…

Python数据分析案例32——财经新闻爬虫和可视化分析

案例背景 很多同学的课程作业都是需要自己爬虫数据然后进行分析&#xff0c;这里提供一个财经新闻的爬虫案例供学习。本案例的全部数据和代码获取可以参考&#xff1a;财经新闻数据 数据来源 新浪财经的新闻网&#xff0c;说实话&#xff0c;他这个网站做成这样就是用来爬虫的…

64.Spring事件监听的核心机制是什么?

Spring事件监听的核心机制是什么? spring的事件监听有三个部分组成 事件(ApplicationEvent) 负责对应相应监听器 事件源发生某事件是特定事件监听器被触发的原因监听器(ApplicationListener) 对应于观察者模式中的观察者。监听器监听特定事件,并在内部定义了事件发生后的响应…

方案解决:5G基站节能及数字化管理

截至2023年10月&#xff0c;我国5G基站总数达321.5万个&#xff0c;占全国通信基站总数的28.1%。然而&#xff0c;随着5G基站数量的快速增长&#xff0c;基站的能耗问题也逐渐日益凸显&#xff0c;基站的用电给运营商带来了巨大的电费开支压力&#xff0c;降低5G基站的能耗成为…

递归、搜索与回溯算法(专题六:记忆化搜索)

目录 1. 什么是记忆化搜索&#xff08;例子&#xff1a;斐波那契数&#xff09; 1.1 解法一&#xff1a;递归 1.2 解法二&#xff1a;记忆化搜索 1.2.1 记忆化搜索比递归多了什么&#xff1f; 1.2.2 提出一个问题&#xff1a;什么时候要使用记忆化搜索呢&#xff1f; 1.3 …

比吸收率(SAR)

本文旨在介绍比吸收率&#xff08;Specific Absorption Rate&#xff09;的基本知识。搬运自https://www.antenna-theory.com。英语够用的朋友可以直接移步。感谢网站创始人Peter Joseph Bevelacqua教授的无私奉献。 ------------------我是分隔线------------------- 比吸收…

视频号的视频怎么下载到手机,视频号下载提取到手机有几个步骤?

要下载视频号的视频并提取到手机&#xff0c;可以按照以下步骤操作&#xff0c;具体一起来看看。 电脑版视频号下载到手机 第一步&#xff1a;找到你心仪的视频号视频在电脑中你也可以通过搜索并找到自己需要的视频并分享给视频下载助手&#xff1b; 第二大步&#xff1a;视频…

C++ 设计模式之备忘录模式

【声明】本题目来源于卡码网&#xff08;题目页面 (kamacoder.com)&#xff09; 【提示&#xff1a;如果不想看文字介绍&#xff0c;可以直接跳转到C编码部分】 【设计模式大纲】 【简介】 -- 什么是备忘录模式 &#xff08;第17种模式&#xff09; 备忘录模式&#xff08;Meme…

如何使用万能头 #include<bits/stdc++.h>

准备蓝桥杯的时候看到了很多头文件包含了这个头文件&#xff0c;后来查了一下 它是C中支持的一个几乎万能的头文件&#xff0c;几乎包含所有的可用到的C库函数。以后写代码就可以直接引用这一个头文件了&#xff0c;不需要在写一大堆vector、string、map、stack…… 我们该如何…

zookeeper弱密码漏洞修复

1.连接zookeeper 进入zookeeper安装目录 bin目录下 ./zkCli.sh -server IP:21812.查看节点 ls /3.查看节点权限 getAcl /zookeeper4.设置IP权限 setAcl / ip:127.0.0.1:cdrwa,ip:10.86.30.11:cdrwazookeeper的权限不具备继承性,父子节点的权限相互独立,因此需要为每个子…

论文阅读笔记AI篇 —— Transformer模型理论+实战 (三)

论文阅读笔记AI篇 —— Transformer模型理论实战 &#xff08;三&#xff09; 第三遍阅读&#xff08;精读&#xff09;3.1 Attention和Self-Attention的区别&#xff1f;3.2 Transformer是如何进行堆叠的&#xff1f;3.3 如何理解Positional Encoding&#xff1f;3.x 文章涉及…

浅析Redis①:命令处理核心源码分析(上)

写在前面 Redis作为我们日常工作中最常使用的缓存数据库&#xff0c;其重要性不言而喻&#xff0c;作为普调开发者&#xff0c;我们在日常开发中使用Redis&#xff0c;主要聚焦于Redis的基层数据结构的命令使用&#xff0c;很少会有人对Redis的内部实现机制进行了解&#xff0c…

龙哥的问题(积性函数,莫比乌斯反演)

题目路径&#xff1a; 221. 龙哥的问题 - AcWing题库 思路&#xff1a;

golang 中使用 statik 将静态资源编译进二进制文件中

现在的很多程序都会提供一个 Dashboard 类似的页面用于查看程序状态并进行一些管理的功能&#xff0c;通常都不会很复杂&#xff0c;但是其中用到的图片和网页的一些静态资源&#xff0c;如果需要用户额外存放在一个目录&#xff0c;也不是很方便&#xff0c;如果能打包进程序发…

《游戏-01_2D-开发》

首先利用安装好的Unity Hub创建一个unity 2D&#xff08;URP渲染管线&#xff09;项目 选择个人喜欢的操作格局&#xff08;这里采用2 by 3&#xff09; 在Project项目管理中将双栏改为单栏模式&#xff08;个人喜好&#xff09; 找到首选项&#xff08;Preferences&#xff09…

带你学C语言-指针(4)

目录 ​编辑 ⚾0.前言 &#x1f3c0;1.回调函数 ⚽2.qsort &#x1f3c9;2.1 qsort函数的模拟实现 &#x1f3be;3.sizeof与strlen对比 &#x1f3be;4.结束语 ⚾0.前言 言C之言&#xff0c;聊C之识&#xff0c;以C会友&#xff0c;共向远方。各位CSDN的各位你们好啊&…

docker 使用 vcs/2018 Verdi等 eda 软件

好不容易在ubuntu 安装好了eda软件&#xff0c;转眼就发现了自己的无知。 有博主几年前就搞定了docker上的EDA工具。而且更全&#xff0c;更简单。只恨自己太无知啊。 Synopsys EDA Tools docker image - EDA资源使用讨论 - EETOP 创芯网论坛 (原名&#xff1a;电子顶级开发网…