一:背景

1. 讲故事

训练营里的一位学员找到我,说他们的系统会出现内存暴涨的情况,看了下也不是托管堆的问题,让我协助一下到底怎么回事?既然有dump了,那就开始分析之旅吧。

二:内存暴涨分析

1. 为什么会暴涨

在分析之前还是那条原则,不要过分的相信求助者的话,否则容易被他带沟里去,毕竟人家是业余的,你是专业的。。。接下来使用 !address -summary 观察下提交内存,输出如下。


0:000> !address -summary--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free                                    637     5ffd`2b0ce000 (  95.989 TB)           74.99%
<unknown>                              2783     2001`3b63cc00 (  32.005 TB)  99.98%   25.00%
Heap                                   3737        1`509cf000 (   5.260 GB)   0.02%    0.00%
Image                                  2615        0`2deb1400 ( 734.692 MB)   0.00%    0.00%
Stack                                   235        0`12d00000 ( 301.000 MB)   0.00%    0.00%
Other                                    80        0`082c8000 ( 130.781 MB)   0.00%    0.00%
TEB                                      78        0`0009c000 ( 624.000 kB)   0.00%    0.00%
PEB                                       1        0`00001000 (   4.000 kB)   0.00%    0.00%--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE                            6681     2002`9d342000 (  32.010 TB) 100.00%   25.01%
MEM_IMAGE                              2625        0`2deca000 ( 734.789 MB)   0.00%    0.00%
MEM_MAPPED                              223        0`09d16000 ( 157.086 MB)   0.00%    0.00%--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                637     5ffd`2b0ce000 (  95.989 TB)           74.99%
MEM_RESERVE                             855     2001`4093a000 (  32.005 TB)  99.98%   25.00%
MEM_COMMIT                             8674        1`945e8000 (   6.318 GB)   0.02%    0.00%
...

从卦中可以看到当前 MEM_COMMIT=6.3GHeap=5.2G,卦象里已经非常明显的表明当前属 NT堆 暴涨,缩小范围之后继续使用 !heap -s 下钻分析。


0:000> !heap -s************************************************************************************************************************NT HEAP STATS BELOW
************************************************************************************************************************
NtGlobalFlag enables following debugging aids for new heaps:stack back traces
LFH Key                   : 0x7a5897d060b6c4ee
Termination on corruption : ENABLEDHeap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast (k)     (k)    (k)     (k) length      blocks cont. heap 
-------------------------------------------------------------------------------------
0000016214c40000 08000002 4711276 4710972 4710884   9187  1416   295   19     6d   LFH
000001620cbd0000 08008000      64      8     64      6     1     1    0      0      
0000016214f60000 08001002    1472    132   1080     21     7     2    0      0   LFH
...

从卦象看,这高内存是由 Heap=0000016214c40000 贡献的,其中 Commit=4.71G 也明确的表明当前是由海量的 alloc <1M 的 block 引发的,由于这个dump已经开启了 stack back traces,所以能够轻松的拿到分配block的调用栈。

2. 海量的block是什么

要想找到这个答案,可以对heap进行分配排序来观察异常特征,使用 !heap -stat -h 0000016214c40000 命令。


0:000> !heap -stat -h 0000016214c40000heap @ 0000016214c40000
group-by: TOTSIZE max-display: 20size     #blocks     total     ( %) (percent of total busy bytes)4000 40e08 - 103820000  (88.20)1000 15a1d - 15a1d000  (7.35)1309800 5 - 5f2f800  (2.02)e6a900 2 - 1cd5200  (0.61)ba6a20 1 - ba6a20  (0.25)3a8000 3 - af8000  (0.23)4ce500 2 - 99ca00  (0.20)800027 1 - 800027  (0.17)...

从卦中可以看到 block=4000byte 的块有 0x40e08 个,总大小为 0x103820000 = 4.3G,看样子离真相越来越近了,接下来使用 !heap -flt s 4000 看下这 0x40e08 个block都是些什么东西,部分输出如下:


0:000> !heap -flt s 4000_HEAP @ 16214c40000HEAP_ENTRY Size Prev Flags            UserPtr UserSize - state000001622fa684a0 0403 0000  [00]   000001622fa684d0    04000 - (busy)...0000016281dcf7b0 0403 0403  [00]   0000016281dcf7e0    04000 - (busy)0000016281dd37e0 0403 0403  [00]   0000016281dd3810    04000 - (busy)0000016281dd7810 0403 0403  [00]   0000016281dd7840    04000 - (busy)0000016281ddb840 0403 0403  [00]   0000016281ddb870    04000 - (busy)0000016281ddf870 0403 0403  [00]   0000016281ddf8a0    04000 - (busy)0000016281de38a0 0403 0403  [00]   0000016281de38d0    04000 - (busy)0000016281de78d0 0403 0403  [00]   0000016281de7900    04000 - (busy)0000016281deb900 0403 0403  [00]   0000016281deb930    04000 - (busy)0000016281def930 0403 0403  [00]   0000016281def960    04000 - (busy)0000016281df3960 0403 0403  [00]   0000016281df3990    04000 - (busy)0000016281df7990 0403 0403  [00]   0000016281df79c0    04000 - (busy)...

接下来就是使用 !heap -p -a 0000016281df7990 抽几个 block 观察其分配栈,全都是如下输出:


0:000> !heap -p -a 0000016281df7990address 0000016281df7990 found in_HEAP @ 16214c40000HEAP_ENTRY Size Prev Flags            UserPtr UserSize - state0000016281df7990 0403 0000  [00]   0000016281df79c0    04000 - (busy)7ffa3dadb49d ntdll!RtlpAllocateHeapInternal+0x0000000000000a7d7ffa3b44fde6 ucrtbase!_malloc_base+0x00000000000000367ff9faacc1a9 xxxWrapper!xxxWrapper::operator=+0x00000000000088197ff9faac5474 xxxWrapper!xxxWrapper::operator=+0x0000000000001ae47ff9faac3efb xxxWrapper!xxxWrapper::operator=+0x000000000000056b7ff9c8c06606 +0x00007ff9c8c06606

从卦象看是 0x00007ff9c8c06606 调用了 xxxWrapper.dll,可能有些人有疑问,前者为什么是地址而不是函数名,这是因为它是JIT动态生成的哈,使用 !ip2md 0x00007ff9c8c06606 让其现出原形。


0:000> !ip2md 0x00007ff9c8c06606
MethodDesc:   00007ff9c8e00068
Method Name:  xxxWrapper.xxxWrapperHelper.GetSpectrum(Int32)
Class:        00007ff9c8ded028
MethodTable:  00007ff9c8e001f8
mdToken:      0000000006000073
Module:       00007ff9c8dbcce8
IsJitted:     yes
CodeAddr:     00007ff9c8c06590
Transparency: Safe critical

最后根据 GetSpectrum 找到相应的源码,截图如下:

从卦中看应该只有分配,没有调用相关的释放 函数导致的,让朋友找一下 GetSpectrum 函数的 C++ 方,定会提供相关指导意见。

三:总结

本次内存暴涨事故属于C++和C#团队没有很好的沟通和协作引发的,不过像这种多语言项目想不弄出点事都难哈。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93831.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93831.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/93831.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于OpenCV的物体识别与计数

在计算机视觉领域&#xff0c;利用图像处理技术进行物体识别和计数是一项基础且重要的任务。本文将介绍一种使用OpenCV库实现的高效物体识别与计数方法&#xff0c;并提供一些代码片段以帮助理解各个步骤。 这是前几年做过传统图像处理计数的项目&#xff0c;通过传统图像处理之…

算法题打卡力扣第34题:在排序数组中查找元素的第一个和最后一个位置(mid)

题目描述提示&#xff1a; 0 < nums.length < 105 -109 < nums[i] < 109 nums 是一个非递减数组 -109 < target < 109 解题思路一 暴力解 头到尾遍历整个数组。 用一个变量 first 记录第一次遇到 target 的索引。 继续遍历&#xff0c;用另一个变量 last 不断…

虚幻基础:曲线

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录曲线&#xff1a;数值变化的曲线动画曲线动画曲线get curve value只有curve所在动画被播放才返回曲线数值没播放时 返回0一个曲线可以在多个动画中使用 且可以设置曲线的不同值曲线&#xff1a;数值变化的曲线 动画…

MFC随笔—不使用对话框资源模板创建对话框

在MFC程序中使用对话框时一般都是首先在资源模版里创建对话框资源,然后DoModal()或者Create显示出模式对话框或者非模式对话框。然而采用该方式创建出的对话框移植性差,从一个工程移动到另一个工程比较麻烦。 在MFC中还有另一种创建对话框的方法,即利用DLGTEMPLATE、DLGITEM…

第八十六章:实战篇:文本生成脚本 → TTS + 镜头 → 视频整合——让你的文字“动听”又“好看”!

AI导演链路前言&#xff1a;AI的“智能制片人”——文本 → 视频&#xff0c;你的想法“一键出片”&#xff01;第一章&#xff1a;痛点直击——传统视频制作&#xff0c;累到“吐血”&#xff01;第二章&#xff1a;探秘“智能制片厂”&#xff1a;流水线上的四大核心模块&…

Linux内核源码详解--缺页异常(Page Fault)处理的核心函数handle_pte_fault

handle_pte_fault 是 Linux 内核中处理缺页异常&#xff08;Page Fault&#xff09;的核心函数&#xff0c;负责根据页表项&#xff08;PTE&#xff09;的状态和访问权限&#xff0c;分发到不同的子处理逻辑&#xff08;如匿名页映射、文件页映射、写时复制、NUMA 迁移等&#…

基于混合注意力网络和深度信念网络的鲁棒视频水印技术基础理论深度解析

1. 引言随着数字媒体技术的迅猛发展和互联网的普及&#xff0c;视频内容的创作、传播和分享变得前所未有的便捷。然而&#xff0c;这种便利性也带来了严重的版权保护挑战。数字视频的易复制性使得盗版和非法传播成为困扰内容创作者和版权所有者的重大问题。传统的加密技术虽然能…

linux 之virtio 的驱动框架

1、基本知识 上一篇文章介绍了 virtio 的核心数据的实现和逻辑&#xff1a;linux 之 virtio 子系统核心的数据结构-CSDN博客 virtio 是对半虚拟化 hypervisor 中的一组通用模拟设备的抽象。它允许 hypervisor 导出一组通用的模拟设备&#xff0c;并通过一个通用的应用编程接口…

项目1总结其三(图片上传功能)

1、UploadService public interface UploadService {//上传图片String uploadImage(MultipartFile file, String type); }upload.location D:/upload Value("${upload.location}")private String uploadLocation;//文件上传路径Overridepublic String uploadImage(M…

Linux应用层开发--线程池介绍

Glib 线程池 1. 线程池简介 线程池是一种管理和重用多个线程的设计模式&#xff1a; 避免频繁创建/销毁线程的开销。提高性能与资源利用率。任务提交后&#xff0c;由线程池内的线程自动执行&#xff0c;任务执行完线程不会退出&#xff0c;而是继续等待下一个任务。 2. Gli…

【Python】Python 多进程与多线程:从原理到实践

Python 多进程与多线程&#xff1a;从原理到实践 文章目录Python 多进程与多线程&#xff1a;从原理到实践前言一、并发编程基础&#xff1a;进程与线程1.1 进程&#xff08;Process&#xff09;1.2 线程&#xff08;Thread&#xff09;1.3 进程与线程的关系二、Python 中的 &q…

electron-vite_18Less和Sass共用样式指定

项目中可以封装less公用样式和方法&#xff0c;比如自动以滚动条样式、单行省略号、多行省略号、display:none等&#xff1b;关于additionalData的配置生效,请在main.js中引入一个别的样式或vue组件中使用“<style lang“scss”><style>”找到electron.vite.config…

Python面试题及详细答案150道(71-80) -- 文件操作篇

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

python新工具-uv包管理工具

uv 是一个由 Astral (Ruff 的创建者) 开发的极速 Python 包和项目管理器&#xff0c;用 Rust 编写。它旨在作为传统 Python 包管理工具&#xff08;如 pip、pip-tools、pipx、poetry、pyenv、twine 和 virtualenv 等&#xff09;的替代品&#xff0c;通过其高性能和多功能集成&…

有关spring-ai的defaultSystem与systemMessage优先级

今天在写项目的时候想用nacos随时修改system的prompt&#xff0c;突然发现defaultSystem的优先级比systemMessage高很多&#xff0c;废话我就不说了&#xff0c;看图吧。你觉得证据不够&#xff1f;那这样呢&#xff1f;

#运维 | 前端 # Linux http.server 实践:隐藏长文件名,简短路径 (http://IP:port/别名 ) 访问

如何运行页面为 http://ip:port/名称 1. 准备文件目录 假设文件原始位置&#xff1a; /home/ubuntu/projects/yinran/ckd.html将它移动到子目录并改名为 index.html&#xff1a; mkdir -p /home/ubuntu/projects/yinran/ckd mv /home/ubuntu/projects/yinran/ckd.html \/home/u…

任务管理器不刷新

记录一个小问题&#xff1a; 进入任务管理器之后发现页面不会刷新&#xff0c;性能界面也是一致。解决办法&#xff1a;查看–>更新速度–>正常

2025-08-21 Python进阶9——__main__与lambda

文章目录1 \_\_main\_\_1.1 name 变量1.1.1 当模块作为主程序直接运行时1.1.2 当模块被其他模块导入时1.2 \_\_main\_\_ 的含义1.3 if \_\_name\_\_ \_\_main\_\_1.5 小结2 lambda表达式2.1 基本概念2.2 lambda 函数语法2.3 使用示例2.4 与高阶函数结合使用2.4.1 与 map () 结…

Java:将视频上传到腾讯云并通过腾讯云点播播放

功能需求:传入一个videoFile也就是视频字节流,返回腾讯云点播的视频保存url需要在腾讯云中寻找的配置信息:导入的依赖:<!--腾讯云点播--><dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java</artifactId&…

Unity3D物理游戏网络同步指南

前言 Unity3D 物理游戏的网络同步是一个复杂但非常核心的话题。要实现一个流畅、公平且可扩展的多人物理游戏&#xff0c;需要深入的理解和精心的设计。 下面我将为你全面解析 Unity3D 物理游戏的网络同步&#xff0c;包括核心概念、主流方案、实现细节以及最佳实践。 对惹&…