<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Linux系列:如何用heaptrack跟蹤.NET程序的heap泄露

      一:背景

      1. 講故事

      前面跟大家分享過一篇 C# 調(diào)用 C代碼引發(fā)非托管內(nèi)存泄露 的文章,這是一個(gè)故意引發(fā)的正向泄露,這一篇我們從逆向的角度去洞察引發(fā)泄露的禍根代碼,這東西如果在 windows 上還是很好處理的,很多人知道開啟一個(gè) ust 即可,讓操作系統(tǒng)幫忙介入,在linux上就相對(duì)復(fù)雜一點(diǎn)了,畢竟Linux系統(tǒng)是一個(gè)萬物生的場地,沒有一個(gè)人統(tǒng)管全局,在調(diào)試領(lǐng)域這塊還是蠻大的一個(gè)弊端。

      二:案例分析

      1. 一個(gè)小案例

      這里我還是用之前的例子,對(duì)應(yīng)的 C 代碼 和 C#代碼 如下:

      1. C 代碼
      
      
      #include <stdlib.h>
      #include <stdio.h>
      #include <stdint.h>
      #include <string.h>
      
      #define BLOCK_SIZE (10 * 1024)              // 每個(gè)塊 10K
      #define TOTAL_SIZE (1 * 1024 * 1024 * 1024) // 總計(jì) 1GB
      #define BLOCKS (TOTAL_SIZE / BLOCK_SIZE)    // 計(jì)算需要的塊數(shù)
      
      void heapmalloc()
      {
          uint8_t *blocks[BLOCKS]; // 存儲(chǔ)每個(gè)塊的指針
      
          // 分配 1GB 內(nèi)存,分成多個(gè)小塊
          for (size_t i = 0; i < BLOCKS; i++)
          {
              blocks[i] = (uint8_t *)malloc(BLOCK_SIZE);
              if (blocks[i] == NULL)
              {
                  printf("內(nèi)存分配失敗!\n");
                  return;
              }
      
              // 確保每個(gè)塊都被實(shí)際占用
              memset(blocks[i], 20, BLOCK_SIZE);
          }
      
          printf("已經(jīng)分配 1GB 內(nèi)存在堆上!\n");
      }
      
      
      1. C#代碼
      
      using System.Runtime.InteropServices;
      
      namespace CSharpApplication;
      
      class Program
      {
          [DllImport("libmyleak.so", CallingConvention = CallingConvention.Cdecl)]
          public static extern void heapmalloc();
      
          static void Main(string[] args)
          {
              heapmalloc();
              Console.ReadLine();
          }
      }
      
      

      2. heaptrack 跟蹤

      heaptrack 是一款跟蹤 C/C++ heap分配的工具,它會(huì)攔截所有的 malloc、calloc、realloc 和 free 函數(shù)調(diào)用,并記錄分配的調(diào)用棧信息,總的來說這工具和 C# 半毛錢關(guān)系都沒有,主要是圖它的如下三點(diǎn):

      1. 能夠記錄到分配的調(diào)用棧信息,雖然只有非托管部分。
      2. 對(duì)程序的影響相對(duì)小。
      3. 有可視化的工具觀察跟蹤文件。

      依次安裝 heaptrackheaptrack-gui ,參考如下:

      
      root@ubuntu2404:/data# sudo apt install heaptrack
      Reading package lists... Done
      Building dependency tree... Done
      Reading state information... Done
      heaptrack is already the newest version (1.5.0+dfsg1-2ubuntu3).
      0 upgraded, 0 newly installed, 0 to remove and 217 not upgraded.
      
      root@ubuntu2404:/data/CSharpApplication/bin/Debug/net8.0# sudo apt install heaptrack-gui
      Reading package lists... Done
      Building dependency tree... Done
      Reading state information... Done
      heaptrack-gui is already the newest version (1.5.0+dfsg1-2ubuntu3).
      0 upgraded, 0 newly installed, 0 to remove and 217 not upgraded.
      
      

      安裝好以后可以用 heaptrack dotnet CSharpApplication.dll 對(duì) dotnet 程序進(jìn)行跟蹤,當(dāng)泄露到一定程序之后,可以用 dotnet-dump 生成一個(gè)轉(zhuǎn)儲(chǔ)文件,然后 Ctrl+C 進(jìn)行中斷,

      
      root@ubuntu2404:/data/CSharpApplication/bin/Debug/net8.0# heaptrack dotnet CSharpApplication.dll
      heaptrack output will be written to "/data/CSharpApplication/bin/Debug/net8.0/heaptrack.dotnet.4368.zst"
      starting application, this might take some time...
      NOTE: heaptrack detected DEBUGINFOD_URLS but will disable it to prevent 
      unintended network delays during recording
      If you really want to use DEBUGINFOD, export HEAPTRACK_ENABLE_DEBUGINFOD=1
      已經(jīng)分配 1GB 內(nèi)存在堆上!
      [createdump] Gathering state for process 4383 dotnet
      [createdump] Writing full dump to file /data/CSharpApplication/bin/Debug/net8.0/core_20250307_102814
      [createdump] Written 1252216832 bytes (305717 pages) to core file
      [createdump] Target process is alive
      [createdump] Dump successfully written in 23681ms
      
      root@ubuntu2404:/data/CSharpApplication/bin/Debug/net8.0# heaptrack stats:
      	allocations:          	122151
      	leaked allocations:   	108551
      	temporary allocations:	4118
      
      root@ubuntu2404:/data/CSharpApplication/bin/Debug/net8.0# ls -lh
      total 1.2G
      -rwxr-xr-x 1 root root  74K Mar  5 22:38 CSharpApplication
      -rw-r--r-- 1 root root  421 Mar  5 21:52 CSharpApplication.deps.json
      -rw-r--r-- 1 root root 4.5K Mar  5 22:38 CSharpApplication.dll
      -rw-r--r-- 1 root root  11K Mar  5 22:38 CSharpApplication.pdb
      -rw-r--r-- 1 root root  257 Mar  5 21:52 CSharpApplication.runtimeconfig.json
      -rw------- 1 root root 1.2G Mar  7 10:28 core_20250307_102814
      -rw-r--r-- 1 root root 277K Mar  7 10:32 heaptrack.dotnet.4368.zst
      -rwxr-xr-x 1 root root  16K Mar  5 21:52 libmyleak.so
      
      

      從卦中看已產(chǎn)生了一個(gè) heaptrack.dotnet.4368.zst 文件,這是一種專有的壓縮格式,可以借助 heaptrack_print 轉(zhuǎn)成 txt 文件,方便從生產(chǎn)上拿下來分析。

      
      root@ubuntu2404:/data/CSharpApplication/bin/Debug/net8.0# heaptrack_print heaptrack.dotnet.4368.zst > heaptrack.txt
      
      

      真實(shí)的場景下肉眼觀察 heaptrack.txt 是不大現(xiàn)實(shí)的,所以還得借助可視化工具,觀察 Bottom-Up 選擇項(xiàng),信息如下:

      • 左邊面板

      可以觀察到 Leaked 最多的是 libmyleak.so 中的 heapmalloc 函數(shù)。

      • 右邊面板

      可以觀察到執(zhí)行 heapmalloc 方法的上層函數(shù),給大家截圖二張。


      稍微仔細(xì)看的話,會(huì)發(fā)現(xiàn)Backtrace上有很多的 unresolved 符號(hào),這個(gè)沒辦法,畢竟人家是 C/C++ 的跟蹤器,和你C#沒關(guān)系,那這些未解析的符號(hào)到底是什么函數(shù)呢?

      3. 未解析符號(hào)的地址在哪里

      既然是 C# 程序,大概率就是 C#方法了,那如何把方法名給找出來呢?熟悉.NET高級(jí)調(diào)試的朋友此時(shí)應(yīng)該輕車熟路了,思路如下:

      1. 尋找 指令地址。

      一般來說解析不出來都會(huì)生成對(duì)應(yīng)的 指令地址 的,這個(gè)可以到 heaptrack.txt 中尋找蛛絲馬跡,截圖如下:

      1. 抓 core 文件

      要想抓 .NET 的 core 文件,dotnet-dump 即可,這個(gè)就不介紹了哈,參考如下:

      
      root@ubuntu2404:/data/CSharpApplication/bin/Debug/net8.0# ps -ef | grep CSharp
      root        4368    2914  0 10:25 pts/0    00:00:00 /bin/sh /usr/bin/heaptrack dotnet CSharpApplication.dll
      root        4383    4368  2 10:25 pts/0    00:00:03 dotnet CSharpApplication.dll
      root        4421    4336  0 10:28 pts/3    00:00:00 grep --color=auto CSharp
      root@ubuntu2404:/data/CSharpApplication/bin/Debug/net8.0# dotnet-dump collect -p 4383
      Writing full to /data/CSharpApplication/bin/Debug/net8.0/core_20250307_102814
      Complete
      root@ubuntu2404:/data/CSharpApplication/bin/Debug/net8.0# ls -lh
      total 1.2G
      -rwxr-xr-x 1 root root  74K Mar  5 22:38 CSharpApplication
      -rw-r--r-- 1 root root  421 Mar  5 21:52 CSharpApplication.deps.json
      -rw-r--r-- 1 root root 4.5K Mar  5 22:38 CSharpApplication.dll
      -rw-r--r-- 1 root root  11K Mar  5 22:38 CSharpApplication.pdb
      -rw-r--r-- 1 root root  257 Mar  5 21:52 CSharpApplication.runtimeconfig.json
      -rw------- 1 root root 1.2G Mar  7 10:28 core_20250307_102814
      -rw-r--r-- 1 root root    0 Mar  7 10:25 heaptrack.dotnet.4368.zst
      -rwxr-xr-x 1 root root  16K Mar  5 21:52 libmyleak.so
      
      

      core_20250307_102814 生成好之后,就可以借助 sos 的 ip2md 尋找這個(gè)指令地址對(duì)應(yīng)的C#方法名了。

      
      root@ubuntu2404:/data/CSharpApplication/bin/Debug/net8.0# dotnet-dump analyze core_20250307_102814
      Loading core dump: core_20250307_102814 ...
      Ready to process analysis commands. Type 'help' to list available commands or 'help [command]' to get detailed help on a command.
      Type 'quit' or 'exit' to exit the session.
      > ip2md 0x7ea6627119f6                                                                                                                          
      MethodDesc:   00007ea6627cd3d8
      Method Name:          ILStubClass.IL_STUB_PInvoke()
      Class:                00007ea6627cd300
      MethodTable:          00007ea6627cd368
      mdToken:              0000000006000000
      Module:               00007ea66279cec8
      IsJitted:             yes
      Current CodeAddr:     00007ea662711970
      Version History:
        ILCodeVersion:      0000000000000000
        ReJIT ID:           0
        IL Addr:            0000000000000000
           CodeAddr:           00007ea662711970  (MinOptJitted)
           NativeCodeVersion:  0000000000000000
      > ip2md 0x7ea662711947                                                                                                                          
      MethodDesc:   00007ea66279f328
      Method Name:          CSharpApplication.Program.Main(System.String[])
      Class:                00007ea6627bb640
      MethodTable:          00007ea66279f358
      mdToken:              0000000006000002
      Module:               00007ea66279cec8
      IsJitted:             yes
      Current CodeAddr:     00007ea662711920
      Version History:
        ILCodeVersion:      0000000000000000
        ReJIT ID:           0
        IL Addr:            00007ea6de8f1250
           CodeAddr:           00007ea662711920  (MinOptJitted)
           NativeCodeVersion:  0000000000000000
      Source file:  /data/CSharpApplication/Program.cs @ 12
      
      

      到這里恍然大悟,然來調(diào)用路徑為:CSharpApplication.Program.Main -> PInvoke -> heapmalloc ,至此真相大白。

      三:總結(jié)

      Linux 上的調(diào)試總覺得少了一位總管太監(jiān),能分析 非托管內(nèi)存的工具 不鳥dotnet, 同樣的,能分析 dotnet托管內(nèi)存的工具 也不鳥非托管內(nèi)存,大家各自為政。。。 讓習(xí)慣使用通殺一切的windbg使用者太不可思議了。
      圖片名稱

      posted @ 2025-03-07 11:10  一線碼農(nóng)  閱讀(1022)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 欧美性猛交xxxx富婆| 性色av无码久久一区二区三区| 亚洲电影天堂av2017| 亚洲第一福利网站在线观看| 久久国产成人午夜av影院| 老司机午夜免费精品视频| 国产综合精品一区二区三区| 亚洲中文久久久精品无码| 精品中文人妻中文字幕| 视频一区视频二区视频三| 日本高清日本在线免费| 自拍偷在线精品自拍偷99| 亚洲精品无码成人aaa片| 日韩人妻av一区二区三区| 四虎库影成人在线播放| 亚洲国产欧美一区二区好看电影 | 377P欧洲日本亚洲大胆| 亚洲一区二区三区水蜜桃 | 国产精品午夜精品福利| 不卡乱辈伦在线看中文字幕| 成人免费无码大片a毛片| 久久精品国产热久久精品国产亚洲| 亚洲欧洲∨国产一区二区三区| 大伊香蕉精品一区视频在线| 中文字幕亚洲综合第一页| 午夜福利精品国产二区| 亚洲国产欧美一区二区好看电影| 国产亚洲精品合集久久久久| 日韩深夜福利视频在线观看| 亚洲人成色99999在线观看| 哈巴河县| 国产成人精品中文字幕| 日本极品少妇videossexhd| 放荡的少妇2欧美版| 成全我在线观看免费第二季| 青草视频在线观看视频| 日韩有码av中文字幕| 亚洲婷婷综合色高清在线| 亚洲天堂久久一区av| 四虎影视一区二区精品| 国产成人精品午夜福利|