malloc hook进行内存泄漏检测

记录下使用malloc的hook形式,写个小的demo,并记录遇到的问题

1. 实现代码:

   CMakeLists.txt和相应的memory_leak.cpp文件

cmake_minimum_required(VERSION 3.14)
project(demo)

set(_SRC
    memory_leak.cpp)

add_library(memory_leak SHARED ${_SRC})
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <execinfo.h>

//实际内存申请的函数
extern void *__libc_malloc(size_t size);
int enable_malloc_hook = 1;
 
extern void __libc_free(void* p);
int enable_free_hook = 1;

void *malloc(size_t size) 
{
	if (enable_malloc_hook) 
    {
		enable_malloc_hook = 0;
        
        void *p = __libc_malloc(size); //重载达到劫持后 实际内存申请
		// void *caller = __builtin_return_address(0); // 0
		
		// char buff[128] = {0};
		// sprintf(buff, "./mem/%p.mem", p);

        // FILE *fp = fopen(buff, "w");
		// // fprintf(fp, "[+%p] --> addr:%p, size:%ld\n", caller, p, size);

        // void* trace[16];
        // char** messages = (char**)NULL;
        // int i, trace_size = 0;
        // trace_size  = backtrace(trace, 16);
        // messages    = backtrace_symbols(trace, trace_size);
        // for (i=0; i<trace_size; ++i) 
        // {
        //     fprintf(fp, "[bt][%s]\n", messages[i]);
        // }

		// fflush(fp);
        
		fclose(fp); //free
		printf("=====Malloc: %p\n", p);

		enable_malloc_hook = 1;
		
        return p;
	} 
    else 
    {
		return __libc_malloc(size);
	}

	return NULL;
}

void free(void *p) 
{
	if (NULL == p)   // 这里加这个判断是因为backtrace函数的调用不知道为什么会调用free并传递的是0x0指针
    {
        return;
    }

    if (enable_free_hook) 
    {
        printf("=====free: %p\n", p);

		enable_free_hook = 0;
 
		char buff[128] = {0};
		sprintf(buff, "./mem/%p.mem", p);
 
		if (unlink(buff) < 0) 
        { // no exist
			printf("double free: %p\n", p);
		}
        __libc_free(p);
        
		// rm -rf p.mem
		enable_free_hook = 1;
	} 
    else 
    {
		__libc_free(p);
	}
}

测试函数:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <thread>
#include <chrono>
int main()
{

    // while (true)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        void * ptr1 = malloc(10);
    }

    return 0;
}

使用方式:

        export LD_PRELOAD=./libmemory_leak.so

        ./demo

2. 遇到问题

  •  为什么memory_leak使用cpp后续,直接执行demo就直接死机

        Segmentation fault (core dumped)

        但是使用.c后缀编译就没问题

        原因:

                应该和CPP的签名有关系,直接在使用memory_leak.cpp编译,并使用

        extern "C"

        {

                //所有代码

        }

        使用OK

  • 上面代码直接运行是可以的,但是为什么gdb的时候会出现死机,感觉是在递归调用,但是逻辑中已经添加了递归的限制,会反复输出二次释放的信息

        直接将memory_leak.cpp的源码直接嵌套在main.cpp中,就可以gdb了,为什么?

        实际使用中应该就使使用独立的动态库然后LD_PRELOAD的方式进行的呀

        

  • 想要直接gdb ./demo | tee log.txt,通过log.txt查看究竟是否真的二次释放了

 可以看到第一个free之前都没有调用malloc,为什么没有调用malloc就调用了free呢?

 猜测:难道除了系统了free还有别的资源free函数被覆盖了,但是这个资源却不是通过malloc申请的?

3. 好的方案

这里有已经实现好的检测方案:

    GitHub - efficios/memleak-finder: Simple memory leak finder.

大家可以在这个基础上进行自定义修改,满足自己的工程需求。

不过在使用这个代码的过程中,遇到一些问题

3.1. 程序卡住

        直接将库应用到项目代码,会出现程序卡住不动的情况,查看堆栈发现:

第一种堆栈现场:       

 感觉是这个线程一直等在这里,是不是锁被一直占用?

第二程堆栈现场:

直接屏蔽掉接口:

add_mh(void *ptr, size_t alloc_size, const void *caller)

del_mh(void *ptr, const void *caller)

程序就可以正常运行了()

        查看完整堆栈会发现,好几个线程都在竞争锁mh_mutex,不过这里只有一把锁,怎么感觉是死锁了呢?

        为什么屏蔽掉上面两个接口,就有好了呢?

        

3.2. 误报输出很多leak

程序启动后,输出一大堆leak,但是我当前感觉不太像是leak的情况,后续需要再确认

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

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

相关文章

SpringCloud:ElasticSearch之索引库操作

ElasticSearch索引库就类似数据库表&#xff0c;mapping映射就类似表的结构。 我们要向ElasticSearch中存储数据&#xff0c;必须先创建“库”和“表”。 1.mapping映射属性 mapping是对索引库中文档的约束&#xff0c;常见的mapping属性包括&#xff1a; type&#xff1a;…

【无人机】采用最基本的自由空间路损模型并且不考虑小尺度衰落(多径多普勒)固定翼无人机轨迹规划(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【Android Audio】TimeCheck机制

TimeCheck机制&#xff08;Android R/S&#xff09; TimeCheck.cpp TimeCheck.h frameworks/av/media/utils/TimeCheck.cpp TimeCheck守护线程的作用&#xff1a; 当audioserver中IAudioFlinger&#xff0c;IAudioPolicyService&#xff0c;IEffect中的每一个binder函数调用时…

E4--光纤接口通信测试应用2023-04-17

1.场景 使用两块开发板A和B&#xff0c;通过光纤接口将在A板上ROM中存储的图片数据转发到B板并显示在B板连接的显示屏上&#xff0c;实现光纤接口通信。 具体场景是&#xff0c;由于A735T片上资源有限&#xff0c;因此ROM IP存储了一张1024*600&#xff08;LVDS屏幕&#xff0…

深拷贝与浅拷贝

目录&#xff1a; 深拷贝与浅拷贝的区别实现深拷贝的方式利用JSON.parse(JSON.stringify())实现深拷贝的局限性cloneDeep与json的对比手写实现cloneDeep 深拷贝与浅拷贝的区别 深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。 深拷贝和浅拷贝的示意图大致如下&a…

SpringBoot——Scheduled定时任务

目录 1.静态定时任务 2.动态定时任务 在一些业务场景中&#xff0c;我们需要定义一些任务在我们指定的时间或是每隔一个时间段就自动执行&#xff0c;来作为任务的前提&#xff0c;保证业务的执行。比如&#xff1a;我们需要一个定时任务&#xff0c;每天早上6点执行&#xf…

多通道振弦传感器无线采集采集仪如何开始使用

多通道振弦传感器无线采集采集仪如何开始使用 开始使用 设备电源 VS208~432 可使用内置电池&#xff08;默认&#xff09;也可使用外部电池工作。 需要特别注意&#xff1a;严禁内置和外部电池&#xff08;电源&#xff09;同时使用&#xff0c;严重时会造成短路起火&#xff0…

靶机精讲之CTF4

主机发现 靶机193 端口扫描 服务扫描 80&#xff0c;25&#xff08;明确版本&#xff09;攻击面更大 web渗透 blog是交互式的程序 发现index可进行手动爆破&#xff08;地址包含&#xff09; http://192.168.10.193/index.html?page../../../../../../../../etc/passwd 无发…

【数据挖掘与商务智能决策】第八章 K近邻算法

第八章 K近邻算法 1.K近邻算法简单代码演示 import pandas as pd df pd.read_excel(葡萄酒.xlsx) df原始样本酒精含量(%)苹果酸含量(%)分类0样本15201样本26102样本34103样本48314样本51021 # 特征变量和目标变量的切分 X_train df[[酒精含量(%),苹果酸含量(%)]] y_train …

PHP实现以函数的方式计算阶乘,使用函数输入数值逆序输出的两个代码程序

目录 前言 一、实现以函数的方式计算阶乘 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 1.3运行截图 二、使用函数输入3个数求和&#xff0c;并以表单形式输出 2.1运行流程&#xff08;思想&#xff09; 2.2代码段 2.3运行截图 前言 1.因多重原因&#xff0c;…

【C++】模板进阶--非类型模板参数模板特化及分离编译

文章目录一、非类型模板参数二、模板的特化1.模板特化的概念2.函数模板的特化3.类模板的特化3.1 全特化3.2 偏特化4.类模板特化应用示例三、模板的分离编译四、模板总结一、非类型模板参数 模板参数分为类型形参与非类型形参&#xff0c;其中&#xff0c;类型形参即出现在模板…

Spring启动及Bean实例化过程来看经典扩展接口

目录 一、Spring启动及Bean实例化过程 二、分析其对应经典扩展接口 三、对开发的指导意义 备注&#xff1a;以下总结只是一些基本的总结思路&#xff0c;具体每个扩展接口的应用后续进行分析总结。 一、Spring启动及Bean实例化过程 Spring启动及Bean实例化的过程&#xff0…

CSS实现三角形的四种方法

方法一&#xff1a;使用 border (常见) 【解释】不设置宽高&#xff0c;用边框大小控制三角型大小 【分解步骤】 设置一个div不设宽高 【示例】 <style>#triangle{width: 0;height: 0;border: 100px solid;border-color: orangered skyblue gold yellowgreen;} </s…

Python第三方库安装

看见更大的Python世界 Python社区PyPI The Python Package Index PyPI: Python Package Index PSF维护的展示全球Python计算生态的主站 学会检索并利用PyPI&#xff0c;找到合适的第三方库开发程序 实例&#xff1a;开发与区块链相关的程序 第1步&#xff1a;在pypi.org…

第01章_Java语言概述

第01章_Java语言概述 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 1. Java知识脉络图 1.1 Java基础全程脉络图 1.2 本章专题与脉络 2. 抽丝剥茧话Java 2.1 当前大学生就业形势 麦可思研究院…

fMRI研究 | 社交情境下的混合情绪

导读 背景&#xff1a;神经科学通常都是单独研究各种情绪&#xff0c;而混合的情绪状态&#xff08;例如愉悦和厌恶、悲伤和快乐的共存&#xff09;在日常生活中很常见。心理生理学和行为学证据表明&#xff0c;混合情绪可能具有不同于其组成情绪的反应特征。然而&#xff0c;…

PHP快速入门02-PHP语言基础

文章目录前言一、 数据类型1.1 String&#xff08;字符串&#xff09;1.2 Integer&#xff08;整型&#xff09;1.3 Float&#xff08;浮点型&#xff09;1.4 Boolean&#xff08;布尔型&#xff09;1.5 Array&#xff08;数组&#xff09;1.6 Object&#xff08;对象&#xff…

重感知还是重地图?其实无需选择

近来&#xff0c;关于自动驾驶应该重感知还是重地图是个热点话题&#xff0c;很多重量级车厂、自动驾驶供应商都开始提出重感知轻地图的方案&#xff0c;并承诺很快能发布出对应的产品。业界也出现了高精地图已“死”等类似的言论。 一时之间&#xff0c;似乎轻地图已经成为了…

SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁

文章目录1、步骤2、具体过程1、引入pom依赖2、修改配置文件3、单元测试4、测试结果3、redis运行情况4、项目中实际应用5、加锁解决缓存击穿问题代码一&#xff08;存在问题&#xff09;代码二&#xff08;问题解决&#xff09;6、新问题7、分布式锁1、步骤 前提条件&#xff1…

Attention is all your need——Transformer论文

摘要 此序列转录模型仅仅依赖于注意力机制&#xff0c;而不使用循环或者是卷积&#xff0c;将循环全部换成了multi-headed self- attention 介绍 RNN的特点、并行程度低。 Attention在RNN上的应用。 引入注意力机制&#xff0c;提高并行度。 背景 使用卷积对长的序列难以…