当前位置: 首页 > news >正文

内存泄漏检测组件 -- hook

目录

hook malloc与free出现的问题

builtin_return_address(N)


C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂

hook malloc与free出现的问题

#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
/*****************************hook******************************/
typedef void *(*malloc_t)(size_t);
malloc_t malloc_f;
typedef void (*free_t)(void *);
free_t free_f;
static int init_hook() {malloc_f = dlsym(RTLD_NEXT, "malloc");free_f = dlsym(RTLD_NEXT, "free");
}
void *malloc(size_t size) {printf("In malloc\n");return NULL;
}
void free(void *ptr) {printf("In free\n");
}
/***************************************************************/
int main() {init_hook();void *p1 = malloc(10);void *p2 = malloc(20);free(p1);
}

出现段错误,gdb看一看 

        printf函数底层会调用malloc函数,如果程序陷入死循环,会不停的调用malloc。我们下面就要去破坏这个递归

        让第一次进入函数的部分执行我们的流程,而递归进去的算第二次进入函数,返回即可。

#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
/*****************************hook******************************/
typedef void *(*malloc_t)(size_t);
int enable_malloc_hook = 1;
malloc_t malloc_f;
typedef void (*free_t)(void *);
int enable_free_hook = 1;
free_t free_f;
static int init_hook() {malloc_f = dlsym(RTLD_NEXT, "malloc");free_f = dlsym(RTLD_NEXT, "free");
}
void *malloc(size_t size) {if (enable_malloc_hook) {enable_malloc_hook = 0;void *p = malloc_f(size);printf("malloc--->ptr:%p size:%zu\n", p, size);enable_malloc_hook = 1;return p;}else {return NULL;}
}
void free(void *ptr) {if (enable_free_hook) {enable_free_hook = 0;printf("free  --->ptr:%p\n", ptr);free_f(ptr);enable_free_hook = 1;}else {return ;}
}
/***************************************************************/
int main() {init_hook();void *p1 = malloc(10);void *p2 = malloc(20);free(p1);
}

builtin_return_address(N)

# 编译器提供的函数,返回第N层调用函数 

1、gcc默认不支持__builtin_return_address(LEVEL)的参数为非0。好像只支持参数为0。

2、__builtin_return_address(0)的含义是,得到当前函数返回地址,即此函数被别的函数调用,然后此函数执行完毕后,返回,所谓返回地址就是那时候的地址。

3、__builtin_return_address(1)的含义是,得到当前函数的调用者的返回地址。注意是调用者的返回地址,而不是函数起始地址。

在__builtin_return_address函数外面套了一层ConvertToVMA。目的是把返回的内存地址转换成VMA地址。

#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <link.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
/*****************************hook******************************/
//
// Created by 68725 on 2022/8/13.
//
#define _GNU_SOURCE#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <link.h>
#include <unistd.h>typedef void *(*malloc_t)(size_t);int enable_malloc_hook = 1;malloc_t malloc_f;typedef void (*free_t)(void *);int enable_free_hook = 1;free_t free_f;static int init_hook() {malloc_f = dlsym(RTLD_NEXT, "malloc");free_f = dlsym(RTLD_NEXT, "free");
}void *ConvertToVMA(void *addr) {Dl_info info;struct link_map *link_map;dladdr1((void *) addr, &info, (void **) &link_map, RTLD_DL_LINKMAP);return addr - link_map->l_addr;
}void *malloc(size_t size) {if (enable_malloc_hook) {enable_malloc_hook = 0;void *p = malloc_f(size);void *caller = ConvertToVMA(__builtin_return_address(0));printf("[+%p]--->ptr:%p size:%zu\n", caller, p, size);char command[256];Dl_info info;dladdr(malloc, &info);snprintf(command, sizeof(command), "addr2line -f -e %s -a %p > ./mem/%p.mem", info.dli_fname, caller, p);system(command);enable_malloc_hook = 1;return p;}else {return malloc_f(size);}
}void free(void *ptr) {if (enable_free_hook) {enable_free_hook = 0;void *caller = ConvertToVMA(__builtin_return_address(0));printf("[-%p]--->ptr:%p\n", caller, ptr);char buff[128] = {0};sprintf(buff, "./mem/%p.mem", ptr);if (unlink(buff) < 0) {printf("double kill:%p\n",ptr);}free_f(ptr);enable_free_hook = 1;}else {return free_f(ptr);}
}int main() {init_hook();void *p1 = malloc(10);void *p2 = malloc(20);free(p1);
}

http://www.lryc.cn/news/7851.html

相关文章:

  • Diffusion model(三): 公式结论
  • Angular笔记(二)组件
  • 微信小程序|基于小程序+C#制作一个超酷的个人简历
  • 华为OD机试 - 最快到达医院的方法(Java JS Python)
  • 92.【SpringCloud NetFilx】
  • [ahk]如何载入Scite的会话Session文件
  • MyISAM和InnoDb的区别
  • K8s管理应用生命周期-Deployment篇
  • 类和对象(下)(二)
  • MapBox-draw绘制插件的使用教程(含修改样式和方法封装)
  • 使用 ONLYOFFICE 转换 API 构建在线文档转换器
  • Kubernetes的负载均衡方案:MetalLB
  • 【项目】Vue3+TS CMS 基本搭建相关配置
  • ros2 dds
  • chain33架构介绍
  • Lucene学习笔记
  • 动态规划【Day01】| 669 · 换硬币、114 · 不同的路径、116 · 跳跃游戏
  • 1.Hello Python
  • C语言实例|编写C程序在控制台打印余弦曲线
  • 《Hadoop篇》------大数据及Hadoop入门
  • TCP核心机制详解(三)
  • 最易上手的爬虫请求库:Requests核心功能速览(下)
  • 生产故障|Kafka ISR频繁伸缩引发性能急剧下降
  • c++终极螺旋丸:₍˄·͈༝·͈˄*₎◞ ̑̑“类与对象的结束“是结束也是开始
  • 【Python--torch.nn.functional】F.normalize用法 + 代码说明
  • 【算法题】1887. 使数组元素相等的减少操作次数
  • GD库图片裁剪指定形状解决办法(PHP GD库 海报)
  • redis的简介及应用场景
  • 2、HAL库利用滴答定时器systick(1ms中断)实现时间计数戳
  • Spring入门学习