欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

.NET Windbg分析某婦產(chǎn)醫(yī)院WPF內(nèi)存溢出

 更新時(shí)間:2022年06月02日 16:38:50   作者:一線碼農(nóng)  
這篇文章主要為大家介紹了.NET  Windbg分析某婦產(chǎn)醫(yī)院WPF內(nèi)存溢出,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一:背景

1. 講故事

上個(gè)月有位朋友找到我,說(shuō)他的程序存在內(nèi)存溢出情況,尋求如何解決。

要解決還得通過(guò) windbg 分析啦。

二:Windbg 分析

1. 為什么會(huì)內(nèi)存溢出

大家都知道內(nèi)存溢出對(duì)應(yīng)著 .NET 中的 OutOfMemoryException 異常,這種異常有可能是托管代碼手工拋出的,也有可能是CLR層面拋出的,言外之意就是可以通過(guò)兩種方式排查。

  • 托管線程是否掛載著異常?
0:000> !t
ThreadCount:      23
UnstartedThread:  0
BackgroundThread: 5
PendingThread:    0
DeadThread:       17
Hosted Runtime:   no
                                                                         Lock  
       ID OSID ThreadOBJ    State GC Mode     GC Alloc Context  Domain   Count Apt Exception
   0    1 362c 00fac868     26020 Preemptive  7ED701A0:00000000 00fa6b60 0     STA 
   5    2 2d70 00fbeba0     2b220 Preemptive  7EBA7AC0:00000000 00fa6b60 0     MTA (Finalizer) 
   7    3 3264 061c8890   102a220 Preemptive  00000000:00000000 00fa6b60 0     MTA (Threadpool Worker) 
  17   15 3f98 19682b90   202b220 Preemptive  7EBB0830:00000000 00fa6b60 0     MTA 
XXXX   16    0 2845fb00     35820 Preemptive  00000000:00000000 00fa6b60 0     Ukn 
  18   14  a7c 2842b1c8   202b220 Preemptive  00000000:00000000 00fa6b60 0     MTA 
XXXX    6    0 2c9b3778   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   18    0 288a1318   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   23    0 288a22f0   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   10    0 2ccf3550   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   21    0 288a1860   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   12    0 288a1da8   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   11    0 2c993640   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX    8    0 2ccf3a98     35820 Preemptive  00000000:00000000 00fa6b60 0     Ukn 
XXXX    9    0 2ccf2030   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX    7    0 2c9aed88   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   26    0 28898308   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   25    0 2c492c68   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX    4    0 2c993b88   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   20    0 2c9af2d0   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   17    0 2c9afd60   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
XXXX   24    0 2c9b1280   1039820 Preemptive  00000000:00000000 00fa6b60 0     Ukn (Threadpool Worker) 
  23   22 2658 2c9b02a8   1029220 Preemptive  7ED5BFF8:00000000 00fa6b60 0     MTA (Threadpool Worker) 

從輸出信息看,這些線程并沒有掛載任何托管異常,我去。。。

  • 是否在 CLR 上拋出

這主要是看 托管堆(heap) 上的內(nèi)存分配或者gc回收造成的內(nèi)存不足,可以用 !ao 命令。

0:000> !ao
There was no managed OOM due to allocations on the GC heap

從輸出信息看也沒有任何異常,尷尬了??????。。。 尼瑪,那到底是因?yàn)槭裁茨兀?/p>

2. 探索溢出原因

出現(xiàn)這種尷尬情況,我只能懷疑生成這個(gè)dump的時(shí)候并沒有g(shù)et到那個(gè)點(diǎn),或者是我的知識(shí)邊界有限,不過(guò)天無(wú)絕人之路,不在那個(gè) 點(diǎn) 也肯定在那個(gè) 點(diǎn) 附近,對(duì)吧,接下來(lái)用 !address -summary 看一下內(nèi)存使用的歸類信息。

0:000> !address -summary
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
<unknown>                              1520          4c185000 (   1.189 GB)  65.57%   59.45%
Image                                  4306          1f140000 ( 497.250 MB)  26.78%   24.28%
Free                                   1133           bf17000 ( 191.090 MB)            9.33%
Heap                                    617           7626000 ( 118.148 MB)   6.36%    5.77%
Stack                                    72           1740000 (  23.250 MB)   1.25%    1.14%
Other                                    34             7b000 ( 492.000 kB)   0.03%    0.02%
TEB                                      24             30000 ( 192.000 kB)   0.01%    0.01%
PEB                                       1              3000 (  12.000 kB)   0.00%    0.00%
--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_MAPPED                              549          34b60000 ( 843.375 MB)  45.42%   41.18%
MEM_PRIVATE                            1718          20424000 ( 516.141 MB)  27.80%   25.20%
MEM_IMAGE                              4307          1f155000 ( 497.332 MB)  26.78%   24.28%
--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_COMMIT                             4904          66ddd000 (   1.607 GB)  88.64%   80.37%
MEM_RESERVE                            1670           d2fc000 ( 210.984 MB)  11.36%   10.30%
MEM_FREE                               1133           bf17000 ( 191.090 MB)            9.33%
--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
PAGE_READONLY                          2272          382cf000 ( 898.809 MB)  48.41%   43.89%
PAGE_READWRITE                         1572          1eead000 ( 494.676 MB)  26.64%   24.15%
PAGE_EXECUTE_READ                       218           dd59000 ( 221.348 MB)  11.92%   10.81%
PAGE_WRITECOPY                          449           133e000 (  19.242 MB)   1.04%    0.94%
PAGE_EXECUTE_READWRITE                  188            ab4000 (  10.703 MB)   0.58%    0.52%
PAGE_NOACCESS                           156             9c000 ( 624.000 kB)   0.03%    0.03%
PAGE_READWRITE | PAGE_GUARD              48             78000 ( 480.000 kB)   0.03%    0.02%
PAGE_READWRITE | PAGE_WRITECOMBINE        1              2000 (   8.000 kB)   0.00%    0.00%
--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
<unknown>                                   1d200000           a001000 ( 160.004 MB)
Image                                        fed1000           36e4000 (  54.891 MB)
Free                                        33dfe000           1082000 (  16.508 MB)
Heap                                        3da84000            a1b000 (  10.105 MB)
Stack                                        1a10000             fd000 (1012.000 kB)
Other                                       7fa40000             33000 ( 204.000 kB)
TEB                                           a4c000              3000 (  12.000 kB)
PEB                                           a3d000              3000 (  12.000 kB)

從上面的 MEM_COMMIT=1.607 GB 80.37% 信息看,當(dāng)前內(nèi)存占用 1.6G,占比 80.37%,可以看出它受到了一個(gè) 2G內(nèi)存 的限制,而且從 !t 輸出中的內(nèi)存地址看,當(dāng)前是 32bit 程序,所以這是一個(gè)經(jīng)典的: 64系統(tǒng)跑著32位程序被2G內(nèi)存限制 的問(wèn)題。

3. 如何突破 2G 限制

要尋找答案,還得看最權(quán)威的 MSDN: 

https://docs.microsoft.com/en-us/windows/win32/memory/memory-limits-for-windows-releases?redirectedfrom=MSDN

破局 還得設(shè)置程序的 IMAGE_FILE_LARGE_ADDRESS_AWARE 標(biāo)記。

關(guān)于具體怎么設(shè)置,我找了三種方法。

  • 使用 LargeAddressAware 安裝包

參見 github: 

https://github.com/KirillOsenkov/LargeAddressAware

  • 使用 editbin

可以在 vs 的生成事件中輸入 editbin /largeaddressaware $(TargetPath)。

  • 使用代碼方式

這種可以直接給生成好的 exe 增加 LargeAddressAware 標(biāo)記,除了標(biāo)記,還能檢測(cè),????

using System;
using System.IO;
namespace PEFile
{
    public class LargeAddressAware
    {
        public static bool IsLargeAddressAware(string filePath)
        {
            bool isLargeAddressAware = false;
            PrepareStream(filePath, (stream, binaryReader) => isLargeAddressAware = (binaryReader.ReadInt16() & 0x20) != 0);
            return isLargeAddressAware;
        }
        public static void SetLargeAddressAware(string filePath)
        {
            PrepareStream(filePath, (stream, binaryReader) =>
            {
                var value = binaryReader.ReadInt16();
                if ((value & 0x20) == 0)
                {
                    value = (short)(value | 0x20);
                    stream.Position -= 2;
                    var binaryWriter = new BinaryWriter(stream);
                    binaryWriter.Write(value);
                    binaryWriter.Flush();
                }
            });
        }
        private static void PrepareStream(string filePath, Action<Stream, BinaryReader> action)
        {
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
            {
                if (stream.Length < 0x3C)
                {
                    return;
                }
                var binaryReader = new BinaryReader(stream);
                // MZ header
                if (binaryReader.ReadInt16() != 0x5A4D)
                {
                    return;
                }
                stream.Position = 0x3C;
                var peHeaderLocation = binaryReader.ReadInt32();
                stream.Position = peHeaderLocation;
                // PE header
                if (binaryReader.ReadInt32() != 0x4550)
                {
                    return;
                }
                stream.Position += 0x12;
                action(stream, binaryReader);
            }
        }
    }
}

更多辦法參考:

https://stackoverflow.com/questions/639540/how-much-memory-can-a-32-bit-process-access-on-a-64-bit-operating-system

三:總結(jié)

總的來(lái)說(shuō),2G 內(nèi)存限制 是一個(gè) 32bit 程序所必須面對(duì)的問(wèn)題,知道了就好解決了,最后有一個(gè)問(wèn)題要解釋下,為什么 commit 內(nèi)存高達(dá) 1.6G,這是因?yàn)獒t(yī)療類的軟件,大多是 FastReport + DevExpress 這些重量級(jí)的經(jīng)典搭配以及大量的圖片資源占用了太多 native memory。

以上就是.NET Windbg分析某婦產(chǎn)醫(yī)院WPF內(nèi)存溢出的詳細(xì)內(nèi)容,更多關(guān)于.NET Windbg WPF內(nèi)存溢出的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • .NET的Ajax請(qǐng)求數(shù)據(jù)提交實(shí)例

    .NET的Ajax請(qǐng)求數(shù)據(jù)提交實(shí)例

    這篇文章主要介紹了.NET的Ajax請(qǐng)求數(shù)據(jù)提交實(shí)例,較為詳細(xì)的分析了Ajax請(qǐng)求、數(shù)據(jù)的提交以及參數(shù)的傳遞技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-01-01
  • asp.net 臨時(shí)數(shù)據(jù)保存實(shí)現(xiàn)代碼

    asp.net 臨時(shí)數(shù)據(jù)保存實(shí)現(xiàn)代碼

    在一個(gè)程序運(yùn)行的時(shí)候往往我們會(huì)回到上一個(gè)頁(yè)面,或者我們會(huì)需要當(dāng)時(shí)留在這個(gè)頁(yè)面的臨時(shí)數(shù)據(jù),例如,我們用百度搜索“腳本”之后我們會(huì)看到很多那啥我就不再說(shuō)了啊!然后我們返回本來(lái)頁(yè)面在文本框內(nèi)會(huì)有“腳本”的字樣,我們一下代碼段就是實(shí)現(xiàn)這個(gè)功能
    2012-04-04
  • 詳解在.net core中完美解決多租戶分庫(kù)分表的問(wèn)題

    詳解在.net core中完美解決多租戶分庫(kù)分表的問(wèn)題

    這篇文章主要介紹了詳解在.net core中完美解決多租戶分庫(kù)分表的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • asp.net上傳Excel文件并讀取數(shù)據(jù)的實(shí)現(xiàn)方法

    asp.net上傳Excel文件并讀取數(shù)據(jù)的實(shí)現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于asp.net上傳Excel文件并讀取數(shù)據(jù)的實(shí)現(xiàn)方法,文中通過(guò)示例代碼以及圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Ajax實(shí)現(xiàn)異步刷新驗(yàn)證用戶名是否已存在的具體方法

    Ajax實(shí)現(xiàn)異步刷新驗(yàn)證用戶名是否已存在的具體方法

    由于要做一個(gè)注冊(cè)頁(yè)面,看到許多網(wǎng)站上都是使用Ajax異步刷新驗(yàn)證用戶名是否可用的,所以自己也動(dòng)手做一個(gè)小實(shí)例
    2014-02-02
  • ASP.NET比較常用的26個(gè)性能優(yōu)化技巧

    ASP.NET比較常用的26個(gè)性能優(yōu)化技巧

    這篇文章主要給大家介紹asp.net中比較常用的26個(gè)性能優(yōu)化技巧,主要設(shè)計(jì)到asp.net中常用的26個(gè)性能優(yōu)化方面的內(nèi)容,對(duì)于asp.net中常用的26個(gè)性能優(yōu)化技巧感興趣的朋友可以參考下本篇文章
    2015-10-10
  • Asp.net防止盜鏈的實(shí)現(xiàn)原理分析

    Asp.net防止盜鏈的實(shí)現(xiàn)原理分析

    今天在書上偶然看到了如何實(shí)現(xiàn)防盜鏈的問(wèn)題,到網(wǎng)上查看了一下盜鏈主要是其他的一些網(wǎng)站引用本站圖片或者下載鏈接。
    2011-01-01
  • .Net?Core和RabbitMQ限制循環(huán)消費(fèi)的方法

    .Net?Core和RabbitMQ限制循環(huán)消費(fèi)的方法

    當(dāng)消費(fèi)者端接收消息處理業(yè)務(wù)時(shí),如果出現(xiàn)異?;蚴蔷苁障⑾⒂肿兏鼮榈却哆f再次推送給消費(fèi)者,這樣一來(lái),則形成循環(huán)的條件,這篇文章主要介紹了.Net?Core和RabbitMQ限制循環(huán)消費(fèi)的方法,需要的朋友可以參考下
    2022-10-10
  • asp.net DataGrid 中文字符排序的實(shí)現(xiàn)代碼

    asp.net DataGrid 中文字符排序的實(shí)現(xiàn)代碼

    在論壇上看到有位朋友希望對(duì)中文按拼音進(jìn)行排序,剛好最近有點(diǎn)空,貼一份原來(lái)一個(gè)同事寫的一個(gè)排序類,僅稍微改動(dòng)了下下,拿出來(lái)分享下.
    2009-09-09
  • asp.net Textbox服務(wù)器控件

    asp.net Textbox服務(wù)器控件

    這篇文章介紹了asp.net Textbox服務(wù)器控件的簡(jiǎn)單實(shí)例,有需要的朋友可以參考一下
    2013-09-09

最新評(píng)論