我的(C#.NET 4.0)应用程序运行了几天,根据从SQLite数据库获取的价格变化来更新模拟帐户。

在任何特定日期,我需要的只是该帐户的当前状态和最新价格。我希望垃圾收集器能够使内存使用保持平稳,我看到的是工作集和专用内存(如System.Diagnostics.GetCurrentProcess()所报告)以及GC.GetTotalMemory(true)的稳定增长:每天大约30万案件。不可避免地,整个过程在经过约12年的模拟后崩溃,此时内存使用量增加了约1GB。

内存使用量或多或少呈线性增加(如果我在每天结束时强制使用GC.Collect(),则非常平滑)。

我推断有些对象是某种方式无法进行垃圾回收的,即使我认为不再需要它们,并曾希望可以在正常的起潮和执行过程中将其清除。

我该如何尝试找出我在不经意间设法造成这种情况的地方?

我已经下载并运行CLRProfiler-但是,它将花费整个周末的大部分时间来整理文档,并且不能保证它将能够为您提供帮助。

我正在研究this question中的引用。总的来说,我知道哪种情况会导致此问题,我更感兴趣的是看看是否有更快的方法来识别具体细节,而无需花费宝贵的时间在我的代码中剔除引用...

注意:该问题似乎与事件无关,并且不涉及图形组件。

最佳答案

您说您可以模拟工作负载以导致应用程序崩溃。要快速找到泄漏,请模拟工作负载,直到内存消耗变大(例如100 MB),然后将WinDbg或VS以及不受管理的调试附加到您的进程中,然后在立即窗口中运行:

.load sos
extension C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll loaded
!dumpheap -stat
total 2885 objects
Statistics:
MT    Count    TotalSize Class Name
7a5eab18        1           12 System.Diagnostics.TraceOptions
(lots of unimportant stuff here)
79332b54      304         7296 System.Collections.ArrayList
79333274       56        11640 System.Collections.Hashtable+bucket[]
793042f4      345        50056 System.Object[]
79330b24     1041        99428 System.String
79332cc0       21    107109728 System.Int32[]

从此(排序的)输出中,您可以告诉您int[]类型有问题。类型:
!DumpHeap -type System.Int32[] (or whichever type you got)
Address       MT     Size
01381a1c 7931e9bc       40
(cut)
075d1000 79332cc0 67108880
03811000 79332cc0 40000016
total 22 objects
Statistics:
MT    Count    TotalSize Class Name
7931e9bc        1           40 System.Int32[][]
79332cc0       21    107109728 System.Int32[]
Total 22 objects

现在您有了对象的地址。选择其中之一并运行
!GCRoot 075d1000

并且您将导致泄漏的原因。另外,您可能需要咨询this tutorial

关于c# - 如何识别未被垃圾收集的不需要的.NET对象?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8359193/

10-10 17:31