咨询热线:13963630596 联系人:魏学俊 地址:辽宁省鞍山市铁西区西解放路222-2号
centos7 lldb 调试netcore应用的内存泄漏和死循环示例(dump文件调试)
来源:opebet备用入口 发布时间:2019-11-14 点击量:33
写个demo来玩一玩linux平台下使用lldb加载sos来调试netcore应用。当然,在真实的产线环境中需要分析的数据和难度远远高于demo所示,所以demo的作用也仅仅只能起到介绍工具的作用。通常正常情况下,分析个几天才能得出一个结论的的结果都还是比较令人开心的!,很多时候分析来分析去也搞不出个所以然,也是很正常的(当然,也是自己学艺不精(^_^))在linux平台下的sos调试远没有在windows下面用windbg来得舒服,该有的命令很多都没有。微软爸爸还要加油努力啊!如果能做到linux下的dmp能在windows下面用windbg之类的工具那就爽翻了,哈哈,当然不可能,臆想一下下拉。
图片有点多,文章有点长,来一个大纲先
准备DEMO程序的代码生成待调试分析的dump文件目前linux下sos支持的命令模拟分析内存泄漏内存泄漏调试分析结论内存泄漏分析疑问一内存泄漏分析疑问二死循环调试分析内存泄漏调试分析结论准备DEMO程序的代码
废话不多说,先上demo程序代码。代码超级简单,模拟内存泄漏就简单的往一个静态list里面每次插入1M的byte[];死循环则就是一个while(true);PS:话说markdown插入代码能不能有收起,展开功能呢。那就爽歪歪拉 @dudu
namespace linxu_dump_lldb.Controllers{ class env { public static bool cpu_flag; public static bool setcpu_flag(bool flag) => cpu_flag = flag; public static bool getcpu_flag() => cpu_flag; public static List<byte[]> memory = new List<byte[]>(); } [Route("api/[controller]/[action]")] [ApiController] public class ValuesController : ControllerBase { public string index() =>(GC.GetTotalMemory(false) / 1024.0 / 1024).ToString("0.00M"); [HttpGet] public void begin_cpu() { env.setcpu_flag(true); Task.Run(() => {while (env.getcpu_flag()){}}); } [HttpGet] public void begin_memory() { var size_1m = 1 * 1024 * 1024; for (int i = 0; i < 100; i++) env.memory.Add(new byte[size_1m]); } [HttpGet] public void end_cpu() => env.setcpu_flag(false); [HttpGet] public void end_memory() { env.memory.Clear(); GC.Collect(); }}}
生成待调试分析的dump文件
生成模拟内存泄漏的dump
请求接口begin_memory来个几次后,然后通过createdump工具生成dump包,执行了4-5次begin_memory,也就是加了大约400-500M的byte[]放到静态变量中
生成死循环的dump包
请求接口begin_cpu开始异步任务进入死循环,然后通过createdump工具生成dump包
目前linux下sos支持的命令
当前dotnet版本2.1.1。如下图所示支持,sos支持的命令,缺少几个比较有用的命令:ProcInfo ,ObjSize ,SyncBlk,其他缺少的赶脚也用不太上。最最重要的是gdb,lldb的调试命令不熟悉,或者说找不到windbg所对应命令还是蛮难受的,需要进一步认真学习才行...
模拟分析内存泄漏
命令走一个,进入lldb。
/usr/local/llvm-3.9.0/bin/lldb dotnet -c /opt/dump_file/memory_dump -o "plugin load /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.1/libsosplugin.so"
dumpheap -stat 分析先走一波。对堆上面的对象进行统计大于2kb的对象看一看
图上反馈byte[]数组对象占的内存最大,而且是远超其他类型的,因此可以判定应该是byte[]在代码的某个地方没有释放。进去跟进去即可。真实情况项目情况很可能是占用内存最大,对象最多的string对象。分析起来真的有时候看运气,凭经验!...(^_^)dumpheap -mt addr(byte[]数组的MT地址) 过滤看看类型是byte[]的都有那些对象。看上去特征特别明显,全是大小为1048600的bte[]对象。接下来随便找一个看看具体对象的数据是什么dumpobj addr(对象地址);查看对象的基本结构内存数据看上去全是 00 00 00。可以说是一个默认的byte[]对象。可以在进入查看一下sos DumpArray -start 0 -length 10 00007fd5febff9d8(对象地址)查看数据对象,上一张图上我们能看到数组的lenght有1048576个,所以加上-start,-length参数,只查看最前面10个对象。不然刷屏得刷死咯。在接着使用sos DumpVC(查看值类型命令) 00007fd611151460(数组元素类型的mt地址) 00007fd5febff9e9(数组元素对象的地址)a 如下图所示,每个数组元素的类型都是byte,他们的value都是0;接下来,我们在看看这些个对象的gcroot对象是谁,也就是说这些个对象到底由谁持有gcroot addr(对象地址)在挨个看一看,能发现我们的这个list对象lenth有400个,_version=501;这是因为我clear过一次,所以。clear+1,add([100])个数组,所以400+100+1=501;如果这是时候有一个objsize命令可以使用,我们就能计算出来这个list是一个400M的丑陋大对象。可惜linux下面木有。那就只能用查看数据的方法看看这个数组的具体详情拉。sos DumpArray -details(可以把每个对象的基本结构都打印出来),能看到他的每一个元素都有1M(size:1048600(0x100018) bytes)大小
内存泄漏调试分析结论
上图种gcroot有3个结果。第一个,用DumpArray查看后发现,应该是一个系统的静态对象,里面存储都是context之类的东西。第二个,就是我们的问题list对象。即List<byte[]>第三个,是第二个list对象的items。所以问题就出在我们这个静态的 list对象上了,那从代码上搜索一下就比较容易发现我们的List<byte[]>在哪里了。
疑问一
上图种是书籍Pro .Net Performance: Optimize Your C# Applications第98页的一个列子,可惜没有搞懂他的这个地址怎么出来的,能直接拉出来堆栈信息...
疑问二
按理来说1M应该等于1048576,那为什么这里显示是1048600呢,多余的24byte是啥玩意呢?dumpobj查看byte[]对象信息dumpmt查看byte[]类型的mt信息x addr(对象地址,x命令是lldb的命令,用户查看地址处的内存数据。可以使用 -c 24指定需要查看多少位数据)x addr 前16位数据小红框标记,最后8位小红框标记。中间的则是1M的01。01:byte数据,代码直接赋值。
for (int i = 0; i < 100; i++){ var x = new byte[size_1m]; for (int j = 0; j < x.Length; j++) x[j] = 1; env.memory.Add(x);}
但是这24位数据内存结构为何这么组织,以及具体的含义就不是特别清楚了,有待考证!!!学艺不精!,准备回家看看C#本质论有没有说到这部分内容...或者哪位大哥可以说清楚一下,不胜感激!!!google搜索的时候发现 Pro .Net Performance: Optimize Your C# Applications,这本书很屌啊!!!,绝壁值得一看,就是英文不行,求中文版啊!!!,好想吐槽一下国内的垃圾编辑或作者,好的书一本都不翻译,垃圾玩意全翻译过来。http://codingsight.com/precise-computation-of-clr-object-size/https://stackoverflow.com/questions/38056513/why-does-windbg-show-system-int32-variables-as-24-bytes
死循环调试分析
clrthreads -live 先看看还在运行的线程有那些。然后通过thread select 线程编号(lldb命令)。来切换到当前线程。线程编号不是列表种的id字段,而是最前面一行的id。lldb 可以通过thread list命令来列举所有线程。
剩下的工作就是体力活动拉,一个一个看,一个一个分析。比如,我们切换到线程3看一看他当前的堆栈信息clrstack命令可以查看当前线程在托管代码种的堆栈信息。dumstack则可以看到非托管代码种的堆栈信息thread backtrace lldb查看堆栈信息的命令。线程3,能看到当前栈在非托管代码中(libcoreclr.so!TwoWayPipe::WaitForConnection),看方法名字也能猜到干嘛的,不太像我们的目标。另外,linux下面ps -T -p 32728 命令可以查看到进行下线程的基本情况top -H -p 32728 更happy。所以在排查高cpu问题的时候能提供许多便利性,反而比内存问题要来得方便很多。(图中的pid等数据不是一致性的。因为在写blog的时候图片是多次截取的。)所以在dump包的时候可以记录下来高cpu的线程id,然后通过thread select 找到对应的线程编号。在然后直接切换过去看一看就完事拉。所以 thread select 30clrstack看一看,嗯!当前线程在 linxu_dump_lldb.Controllers.ValuesController+<>c.b__1_0() [C:Usersczd89sourceeposConsoleApp4linxu_dump_lldbControllersValuesController.cs @ 31]。看一看当前栈上面都有一些上面参数CLRStack [-a] [-l] [-p];-p:看参数,-l:看局部变量,-a:=-l+-p;当然,我们的代码是异步的,也没有捕获任何action里面的变量,所以这里的这个参数,以及参数里面的属性啥都没有。从dll反编译代码也能和我们lldb看到的东西一一对以上。
内存泄漏调试分析结论
到这里,问题就很明显能看出来了,当然主要还是我们的DEMO是最简单的。还是开篇说过的那句话:通常正常情况下,分析个几天才能得出一个结论的的结果都还是比较令人开心的!,很多时候分析来分析去也搞不出个所以然,也是很正常的(当然,也是自己学艺不精(^_^),当自勉!)还能看一看具体方法的汇编代码等信息。
参考资料:https://docs.microsoft.com/en-us/dotnet/framework/tools/sos-dll-sos-debugging-extensionhttps://github.com/dotnet/coreclr/blob/master/Documentation/building/debugging-instructions.mdhttps://lldb.llvm.org/tutorial.htmlhttps://stackoverflow.com/questions/38056513/why-does-windbg-show-system-int32-variables-as-24-byteshttp://codingsight.com/precise-computation-of-clr-object-size/https://zhuanlan.zhihu.com/p/20838172https://blog.csdn.net/inuyashaw/article/details/55095545
, 1, 0, 9);相关产品
-
不计成本的价格战对于消费者来说,真是利好吗?在网约车消费中,消费者的哪些权益亟须保护? “从表面上看价格战能让用户得到短期优惠,但实际上会对消费者带来长期利空。”曹磊分析,打价格战的网约车平台为了尽快增加车源、拓展业务范围、争夺流量入口,会有意无意地降低对网约车的准入审核门槛,这将带来安全隐患。“馅饼的背后往往是陷阱,这种靠疯狂补贴抢占市场的行为,注定不会持续太久。”中国消费者权益保护法学研究会副秘书长陈音江说。
-
当地时间9月29日上午,美国新泽西霍博肯车站一列通勤火车发生脱轨事故,最新消息显示,事故造成1人死亡,108人受伤。中国驻纽约总领馆称,一名男性中国公民在事故中受伤,无生命危险。图为事故现场。
-
自“王者荣耀”、“球球大作战”、“穿越火线”等现象级手游项目大热之后,绝大部分的豪门俱乐部也纷纷开设了手游项目相关的分部,比如刚刚夺下2017王者冠军杯的QGhappy战队,就是与AutoFull傲风电竞椅合作的QG俱乐部的“王者荣耀”分部。而这次与AutoFull傲风合作的是电竞圈中稀有的女子战队RE—Girls,这支战队由北京聚梦互娱传媒公司组建,征战过KOC,TGA等大型赛事,获得了2017“大豫网杯”王者荣耀女神挑战赛冠军,VIVO王者荣耀嘉年华亚军等卓越战绩。
-
中国海关的数据显示,相比于2015年,澳大利亚葡萄酒2016年的进口量上升了40%,进口额上涨23%。在关税下降、国内需求增长等利好因素的持续推动下,澳大利亚葡萄酒势必将成为国内市场不容忽视的一支重要力量。在此背景下,丁戈树以强劲势头冲击澳洲葡萄酒销售冠军,不仅将改变进口葡萄酒领域的竞争格局,更将对国内葡萄酒市场的发展产生积极而深远的影响。
-
联合声明说,双方认为,在当前国际形势复杂深刻演变的背景下,有必要继续加强在联合国、上海合作组织、亚洲相互协作与信任措施会议(以下称亚信)、亚欧会议等多边机制内的协调与合作,共同应对全球和区域性挑战,维护两国共同利益,保障本地区乃至世界的和平与安全。
-
原来在台北时尚男女无以计数的美梦中,与书的邂逅并非巧合,他们每往前迈一步,依旧懂得对书籍抱着请其指点迷津的尊崇。
-
电影里的英雄,除了拥有侠义的心肠、过人的胆识、非凡的能力,也拥有专业的设备。这一点和成都白蚁所的“白蚁特工队”的队员们何其相似。白蚁作为一种已经在这个地球上存活了上亿年的物种,要想和它们战斗,非一般人能胜任。
-
12月27日下午2时,台湾地区“大选”候选人首场电视辩论登场,两岸话题成为辩论会上的交锋热点。这次电视辩论由传统的“四报一社加公视”、三立电视台等9家媒体联合主办,国民党候选人朱立伦、民进党候选人蔡英文、亲民党候选人宋楚瑜分别就两岸关系、两岸经贸等议题阐述政见,回答媒体提问。
热点资讯
- 哪里的中国人最怕热2019-10-29
- 美国F22正面临着被击落的挑战和风险。航程只有中国|中国|隐形战斗机|20新浪军事的20.50%2019-06-17
- 谷歌任命首席隐私官:政府不断施加监管压力2019-11-12
- 美参议员重击亚马逊:起草“阻止贝索斯”法案要求提高员工工资2019-11-10
- python网络编程-udp2019-11-10
- 荠菜都有哪些功效2019-11-14
- Windows是“丢弃”,而Linux是最终的?创纪录新浪科技2019-06-17
- 微软竞标美国防部项目遭员工反对:不应将AI及云技术用于战争2019-10-29