使用`LD_PRELOAD`和`jemalloc`实现C/C++信号的内存堆栈信息收集
文章目录
- 0. 概要
- 1. 编译jemalloc
- 2. 编译钩子共享库liballoc_hook.so
- 3. 使用`LD_PRELOAD`加载钩子库liballoc_hook.so测试
- 3.1 设置环境变量
- 3.2 使用`LD_PRELOAD`加载钩子库并运行程序
- 3.3 发送`SIGUSR1`信号以触发堆栈信息打印
- 3.4 使用jeprof解析heap堆栈信息文件
- 4. 示例程序example.cpp代码
- 5. 注意事项
- 6. jemalloc的限制
0. 概要
本文介绍如何结合LD_PRELOAD与jemalloc,在接收到SIGUSR1信号时打印程序的堆栈信息。详细步骤包括编译和配置jemalloc,编写信号处理程序,并通过LD_PRELOAD加载共享库的方法。
1. 编译jemalloc
编译并安装启用prof功能的jemalloc。以下是Ubuntu 18.04上的编译步骤:
git clone https://github.com/jemalloc/jemalloc.git # 本文测试的版本是jemalloc-5.3.0
cd jemalloc
./configure --prefix=/usr/local --enable-prof CFLAGS="-fPIC"
make -j10
sudo make install
确保编译 libjemalloc.a 时使用了 -fPIC 选项。
2. 编译钩子共享库liballoc_hook.so
创建一个名为alloc_hook.c的文件,并实现信号处理函数:
/*gcc -o liballoc_hook.so -shared -fPIC alloc_hook.c -Wl,-Bstatic -ljemalloc -Wl,-Bdynamic
*/
#include <jemalloc/jemalloc.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>// 信号处理函数
void handle_signal(int signum) {if (signum == SIGUSR1) {// 触发 jemalloc 的 heap profiling dumpmallctl("prof.dump", NULL, NULL, NULL, 0);printf("Heap profile dump generated.\n");}
}// 初始化函数
void __attribute__((constructor)) init_hook() {// 设置信号处理函数signal(SIGUSR1, handle_signal);printf("Signal handler for SIGUSR1 is set.\n");
}
使用以下命令编译liballoc_hook.so并静态链接libjemalloc.a:
gcc -o liballoc_hook.so -shared -fPIC alloc_hook.c -Wl,-Bstatic -ljemalloc -Wl,-Bdynamic -lpthread
3. 使用LD_PRELOAD加载钩子库liballoc_hook.so测试
假设你的目标程序是example,通过LD_PRELOAD加载liballoc_hook.so钩子库,按照以下步骤运行和测试:
3.1 设置环境变量
export MALLOC_CONF="prof:true,prof_active:true,lg_prof_sample:0,tcache:false,prof_prefix:jeprof.out"
prof:true:启用配置文件。prof_active:true:启用性能分析。lg_prof_sample:0:设置采样率为最高。tcache:false:禁用线程缓存,可能影响性能,但在进行性能分析时,可以提供更准确的内存分配数据。prof_prefix:jeprof.out:指定性能分析输出文件前缀。
3.2 使用LD_PRELOAD加载钩子库并运行程序
LD_PRELOAD="/path/to/liballoc_hook.so" ./example
3.3 发送SIGUSR1信号以触发堆栈信息打印
killall -10 example
# 或者
killall -SIGUSR1 example
通过以上步骤,你可以在接收到SIGUSR1信号时打印jemalloc的堆栈信息,并将其输出到本地目录。本文得到的堆栈信息文件名为jeprof.out.60571.0.m0.heap。
3.4 使用jeprof解析heap堆栈信息文件
通过如下命令分析该堆栈信息文件:
jeprof --show_bytes --text --lines ./example ./jeprof.out.60571.0.m0.heap
解析结果示例如下:
$ jeprof --show_bytes --text --lines ./example jeprof.out.60571.0.m0.heap
Using local file ./example.
Using local file jeprof.out.60571.0.m0.heap.
Total: 83512 B82944 99.3% 99.3% 82944 99.3% prof_backtrace_impl /tmp/jemalloc-5.3.0/src/prof_sys.c:103448 0.5% 99.9% 448 0.5% allocateIntArray /home/test/jemalloc_test/example.cpp:1380 0.1% 100.0% 80 0.1% allocateDynamicArray /home/test/jemalloc_test/example.cpp:32 (discriminator 1)32 0.0% 100.0% 32 0.0% allocateString /home/test/jemalloc_test/example.cpp:258 0.0% 100.0% 8 0.0% allocateDouble /home/test/jemalloc_test/example.cpp:190 0.0% 100.0% 1024 1.2% _IO_new_file_overflow /build/glibc-2ORdQG/glibc-2.27/libio/fileops.c:7590 0.0% 100.0% 1024 1.2% _IO_new_file_xsputn /build/glibc-2ORdQG/glibc-2.27/libio/fileops.c:12660 0.0% 100.0% 1024 1.2% _IO_puts /build/glibc-2ORdQG/glibc-2.27/libio/ioputs.c:400 0.0% 100.0% 1024 1.2% __GI__IO_doallocbuf /build/glibc-2ORdQG/glibc-2.27/libio/genops.c:3650 0.0% 100.0% 1024 1.2% __GI__IO_file_doallocate /build/glibc-2ORdQG/glibc-2.27/libio/filedoalloc.c:1010 0.0% 100.0% 568 0.7% __libc_start_main /build/glibc-2ORdQG/glibc-2.27/csu/../csu/libc-start.c:3100 0.0% 100.0% 82944 99.3% _dl_start_user :?0 0.0% 100.0% 568 0.7% _start ??:?0 0.0% 100.0% 448 0.5% allocateMemory /home/test/jemalloc_test/example.cpp:510 0.0% 100.0% 8 0.0% allocateMemory /home/test/jemalloc_test/example.cpp:520 0.0% 100.0% 32 0.0% allocateMemory /home/test/jemalloc_test/example.cpp:530 0.0% 100.0% 80 0.1% allocateMemory /home/test/jemalloc_test/example.cpp:540 0.0% 100.0% 82944 99.3% call_init /build/glibc-2ORdQG/glibc-2.27/elf/dl-init.c:720 0.0% 100.0% 82944 99.3% imalloc (inline) /tmp/jemalloc-5.3.0/src/jemalloc.c:26940 0.0% 100.0% 82944 99.3% imalloc_body (inline) /tmp/jemalloc-5.3.0/src/jemalloc.c:25500 0.0% 100.0% 1024 1.2% init_hook ??:?0 0.0% 100.0% 82944 99.3% je_malloc_default /tmp/jemalloc-5.3.0/src/jemalloc.c:27220 0.0% 100.0% 82944 99.3%je_prof_backtrace /tmp/jemalloc-5.3.0/src/prof_sys.c:2840 0.0% 100.0% 82944 99.3% je_prof_tctx_create /tmp/jemalloc-5.3.0/src/prof.c:1950 0.0% 100.0% 568 0.7% main /home/test/jemalloc_test/example.cpp:600 0.0% 100.0% 82944 99.3% prof_alloc_prep (inline) /tmp/jemalloc-5.3.0/include/jemalloc/internal/prof_inlines.h:1410 0.0% 100.0% 81920 98.1% std::__once_callable ??:0
4. 示例程序example.cpp代码
以下是完整的example.cpp代码,编译方法: g++ -g -o example example.cpp:
#include <sys/mman.h> // mmap, munmap
#include <unistd.h> // usleep
#include <csignal> // signal, sigaction
#include <cstdlib> // rand()和srand()
#include <ctime> // time()
#include <iostream>
#include <string>
#include <vector>// 分配int数组
void allocateIntArray() {const int* intPtr = new int[100];std::cout << "Allocated int array at: " << intPtr << std::endl;
}// 分配double
void allocateDouble() {const double* doublePtr = new double(3.14);std::cout << "Allocated double at: " << doublePtr << ", value: " << *doublePtr << std::endl;
}// 分配字符串
void allocateString() {const std::string* strPtr = new std::string("Hello, World!");std::cout << "Allocated string at: " << strPtr << ", value: " << *strPtr << std::endl;
}// 分配动态数组
void allocateDynamicArray() {size_t arraySize = 10;size_t* const arrayPtr = new size_t[arraySize];std::cout << "Allocated array of " << arraySize << " ints at: " << arrayPtr << std::endl;for (size_t i = 0; i < arraySize; ++i) {arrayPtr[i] = i;}
}// 使用mmap分配内存
void allocateMmap() {size_t mmapSize = 4096; // 4KBconst void* mmapPtr = mmap(nullptr, mmapSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);if (mmapPtr == MAP_FAILED) {perror("mmap failed");} else {std::cout << "Allocated mmap at: " << mmapPtr << ", size: " << mmapSize << " bytes" << std::endl;}
}void allocateMemory() {allocateIntArray();allocateDouble();allocateString();allocateDynamicArray();allocateMmap();
}int main() {usleep(100000); // 100msallocateMemory();while (true) {usleep(100000); // 100ms}return 0;
}
5. 注意事项
-
编译
libjemalloc.a时请记得添加CFLAGS="-fPIC":./configure --prefix=/usr/local --enable-prof CFLAGS="-fPIC" -
liballoc_hook.so必须是静态链接libjemalloc.a。 -
liballoc_hook.so需要动态链接libpthread.so,编译时记得切回动态链接方式:gcc -o liballoc_hook.so -shared -fPIC alloc_hook.c -Wl,-Bstatic -ljemalloc -Wl,-Bdynamic -lpthread -
请勿使用动态加载
libjemalloc.so。如果使用如下命令:LD_PRELOAD="/path/to/liballoc_hook.so /usr/local/lib/libjemalloc.so" ./example
jeprof解析heap的结果会显示为:
$ jeprof --show_bytes --text --lines ./example ./jeprof.out.60571.0.m0.heap
Using local file ./example.
Using local file ./jeprof.out.60571.0.m0.heap.
Total: 83512 B83512 100.0% 100.0% 83512 100.0% prof_backtrace_impl /tmp/jemalloc-5.3.0/src/prof_sys.c:1030 0.0% 100.0% 568 0.7% 0x00005610af62de49 ??:00 0.0% 100.0% 448 0.5% 0x00005610af62df3b ??:00 0.0% 100.0% 8 0.0% 0x00005610af62df8e ??:00 0.0% 100.0% 32 0.0% 0x00005610af62e039 ??:00 0.0% 100.0% 80 0.1% 0x00005610af62e137 ??:00 0.0% 100.0% 448 0.5% 0x00005610af62e299 ??:00 0.0% 100.0% 8 0.0% 0x00005610af62e29e ??:00 0.0% 100.0% 32 0.0% 0x00005610af62e2a3 ??:00 0.0% 100.0% 80 0.1% 0x00005610af62e2a8 ??:00 0.0% 100.0% 568 0.7% 0x00005610af62e2c3 ??:0
可以看到example.cpp部分的信息无法显示,因此不可使用LD_PRELOAD同时加载liballoc_hook.so和libjemalloc.so。
6. jemalloc的限制
尽管jemalloc在内存管理和性能分析方面具有强大的功能,但它也存在一些限制:
-
无法hook mmap
jemalloc无法hook通过mmap或munmap进行的内存分配。这意味着如果程序中大量使用mmap进行内存分配,这部分内存不会被jemalloc监控和管理,也不会包含在jemalloc的内存分析报告中。因此,对于需要分析这种内存分配行为的程序,jemalloc可能不是最佳选择。 -
无法hook线程相关信息
jemalloc无法直接监控线程的创建和销毁。这对于某些需要详细分析线程行为的应用程序来说是一个限制。尽管jemalloc可以通过配置和编译选项优化内存分配以适应多线程环境,但它不能提供与线程操作相关的详细信息。 -
无法hook直接系统调用的内存分配
如果程序通过直接系统调用(如brk或其他系统级内存分配调用)分配内存,这些调用将绕过jemalloc的内存管理机制。因此,jemalloc无法跟踪这些内存分配行为,导致分析结果不完整。 -
高采样率对性能的影响
开启高采样率(如lg_prof_sample:0)会显著影响程序的性能。虽然高采样率能够提供更详细和频繁的内存分配数据,但它也会导致程序运行速度变慢。因此,在生产环境中需要权衡采样率和性能之间的关系。 -
配置和使用复杂度
正确配置和使用jemalloc需要一定的专业知识和经验。对于不熟悉内存管理和性能分析的开发者来说,jemalloc的配置选项和参数可能显得复杂,容易出错。因此,在使用jemalloc进行内存分析之前,建议详细阅读官方文档并进行充分测试。 -
与其他内存管理库的兼容性问题
在某些情况下,jemalloc可能与其他内存管理库或工具产生兼容性问题。这可能导致程序在链接和运行时遇到问题。因此,在将jemalloc集成到现有项目时,需要进行全面的测试以确保兼容性。
总的来说,尽管jemalloc是一款功能强大的内存管理库,但在使用过程中需要注意其自身的限制,并根据具体需求进行权衡和取舍。
相关文章:
使用`LD_PRELOAD`和`jemalloc`实现C/C++信号的内存堆栈信息收集
文章目录 0. 概要1. 编译jemalloc2. 编译钩子共享库liballoc_hook.so3. 使用LD_PRELOAD加载钩子库liballoc_hook.so测试3.1 设置环境变量3.2 使用LD_PRELOAD加载钩子库并运行程序3.3 发送SIGUSR1信号以触发堆栈信息打印3.4 使用jeprof解析heap堆栈信息文件 4. 示例程序example.…...
计算机组成原理(四)Cache存储器
文章目录 Cache存储器的基本原理cache命中率、平均访问时间、效率地址映射全相联映射直接映射组相联映射 查找算法cache 存储器替换策略cache 存储器-写操作策略习题 Cache存储器的基本原理 Cache是一种高速缓冲寄存器,是为了解决CPU和主存之间速度不匹配而采用的一…...
怎么做成的文件二维码?扫阅览文件的制作方法
现在用二维码来分享或者查看文件是一种很常用的方式,比如常见的文件内容有简历、资料、作品、压缩包等等。通过将文件生成二维码能够在提升文件传输速度的同时还有利于用户体验的提升,那么如何制作可以长期提供文件预览或者下载的二维码呢? …...
js 前端 Function.prototype.call.call(0[‘toString‘], *, 16)
这个函数将 数组转任意进制 Function.prototype.call.call(0[toString], *, 16)...
李沐:用随机梯度下降来优化人生!
大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 今天我们来聊聊达叔 6 大核心算法之 —— 优化 算法。吴恩达:机器学习的六个核心算法! 梯度下降优化算法是机器…...
Linux 环境.Net程序堆栈查询
# 安装 dotnet tool install --global dotnet-dump# 收集信息, 产生 core_XXX 文件 dotnet-dump collect -p pid# 分析 core_XXX 文件 dotnet dump analyze core_XXX# 列出 大于 XXX 字节的 对象 dumpheap -stat -min XXX# 查看对象具体信息 dumpobj address_XXX# 查看对应引用…...
志愿服务管理系统的设计
管理员账户功能包括:系统首页,个人中心,管理员管理,基础数据管理,广场论坛管理,志愿活动管理,活动报名管理 前台账户功能包括:系统首页,个人中心,志愿活动&a…...
微信小游戏5月畅销榜,新老产品更替显著,亿级爆款频出
小游戏由于微信的平台扶持,被视为可以大力发掘的蓝海,成为国内游戏最大的增长机会之一,随着越来越多的大厂和中小厂转向了小游戏赛道,每个月的小游戏畅销榜单都有不同变化。 5月的小游戏畅销榜显示,小游戏市场正经历显…...
自己想要公开自己的学习方法,但是自己很害怕自己的学习方法是一个错误的,因为对于自己而言,专升本的机会只有一次
分享自己的学习方法可能需要一定的勇气,特别是当你担心可能会受到批评或是不被理解时。以下是一些建议,可以帮助你克服这种恐惧:(kimi编辑器自己对于这些内容的基础批注) 自我肯定:首先,认识到你…...
linux centos consul1.15.2一键安装部署
consul原理、作用、安装相关内容 一、理论部分二、安装下载版本地址三、安装consul服务 一、理论部分 1、consul的原理 Consul的原理及作用可以归纳为以下几点: ①、基于Gossip协议的通信:Consul使用了基于Gossip协议的Serf实现来进行通信。 Gossip协议…...
速盾:dns和cdn区别?
DNS(Domain Name System)和CDN(Content Delivery Network)是互联网中两个不同但相互关联的服务。下面将详细解释DNS和CDN的区别。 功能和作用: DNS:DNS是将域名转换为IP地址的服务,它充当着互联…...
多目标跟踪中用到的求解线性分配问题(Linear Assignment Problem,LAP)C++
多目标跟踪中用到的求解线性分配问题(Linear Assignment Problem,LAP)C flyfish python实现,说的比这里详细 lapjv.h和lapjv.cpp代码在https://github.com/shaoshengsong/DeepSORT C代码调用 #include <iostream> #include <ve…...
Unity | Shader基础知识(第十四集:简单效果练习)
目录 前言 一、效果预览 1.弧形边缘光 二、效果制作 1. 制作弧形边缘光 2.弧形边缘光进阶 3.弧形边缘光调节渐变范围 4.边缘光突变 5.同心圆 三、加入世界坐标做效果 1.绘制结界 2.斑马球 3.效果合并 四、作者的碎碎念 前言 有粉丝建议说,让我继续更新…...
Vue48-ref属性
一、需求:操作DOM元素 1-1、使用原生的id属性 不太好! 1-2、使用 ref属性 原生HTML中,用id属性给元素打标识,vue里面用ref属性。 给哪个元素加了ref属性,vc实例对象就收集哪个元素!!࿰…...
【SpringCloud学习笔记】RabbitMQ(中)
1. 交换机概述 前面《RabbitMQ上篇》我们使用SpringAMQP来演示如何用Java代码操作RabbitMQ,当时采用的是生产者直接将消息发布给队列,但是实际开发中不建议这么做,更加推荐生产者将消息发布到交换机(exchange),然后由exchange路由…...
【C++】类和对象的引入
文章目录 前言一、类的定义二、类的访问控制与封装三、类的作用域四、类的实例化五、类的存储方式及大小计算六、隐藏的this指针 前言 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 C是基于面向对象的&…...
11.5.k8s中pod的调度-cordon,drain,delete
目录 一、概念 二、使用 1.cordon 停止调度 1.1.停止调度 1.2.解除恢复 2.drain 驱逐节点 2.1.驱逐节点 2.2.参数介绍 2.3.解除恢复 3.delete 删除节点 一、概念 cordon节点,drain驱逐节点,delete 节点,在对k8s集群节点执行维护&am…...
Java中线程的创建方式
一、继承Thread类,重写run方法 public class MyThread{public static void main(String[] args) {Thread threadDome new ThreadDome();threadDome.start();} }class ThreadDome extends Thread{Overridepublic void run() {for (int i 0; i < 5; i) {try {Th…...
猫头虎推荐20个值得体验的通用大模型
猫头虎推荐20个值得体验的通用大模型 🚀 大家好,我是猫头虎,一名专注于科技领域的自媒体博主。今天是周一,新的开始,我们来深入探讨一下当前最值得体验的通用大模型。这些AI模型不仅功能强大,而且在各自领…...
Novartis诺华制药社招综合能力性格动机问卷入职测评笔试题库答案及包过助攻
【华东同舟求职】由资深各行业从业者建立的一站式人才服务网络平台,现阶段目标是“提升全市场各行业岗位信息的流动性和透明度”。我们接受众多行业机构的直接委托发布,并尽力通过各种方法搜寻高价值岗位信息。事实上,我们以发现不为人知的优…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
