【发布时间】:2010-11-20 17:55:48
【问题描述】:
我有一个应用程序,由于在对象引用设置为 null 之前未分离事件而导致一些内存泄漏。应用程序很大,通过查看代码很难找到内存泄漏。我想使用 sos.dll 来查找作为泄漏源的方法的名称,但我被卡住了。我设置了一个测试项目来演示这个问题。
这里我有 2 个类,一个有一个事件,并在监听该事件,如下所示
namespace MemoryLeak
{
class Program
{
static void Main(string[] args)
{
TestMemoryLeak testMemoryLeak = new TestMemoryLeak();
while (!Console.ReadKey().Key.Equals('q'))
{
}
}
}
class TestMemoryLeak
{
public event EventHandler AnEvent;
internal TestMemoryLeak()
{
AnEventListener leak = new AnEventListener();
this.AnEvent += (s, e) => leak.OnLeak();
AnEvent(this, EventArgs.Empty);
}
}
class AnEventListener
{
public void OnLeak()
{
Console.WriteLine("Leak Event");
}
}
}
我闯入代码,并在中间窗口输入
.load sos.dll
然后我使用 !dumpheap 来获取 AnEventListener 类型的堆上的对象
!dumpheap -type MemoryLeak.AnEventListener
我得到以下信息
PDB symbol for mscorwks.dll not loaded
Address MT Size
01e19254 0040348c 12
total 1 objects
Statistics:
MT Count TotalSize Class Name
0040348c 1 12 MemoryLeak.AnEventListener
Total 1 objects
我使用 !gcroot 来找出对象没有被垃圾回收的原因
!gcroot 01e19254
并得到以下
!gcroot 01e19254
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Error during command: Warning. Extension is using a callback which Visual Studio
does not implement.
Scan Thread 5208 OSTHread 1458
ESP:2ef3cc:Root:01e19230(MemoryLeak.TestMemoryLeak)->
01e19260(System.EventHandler)->
01e19248(MemoryLeak.TestMemoryLeak+<>c__DisplayClass1)->
01e19254(MemoryLeak.AnEventListener)
Scan Thread 7376 OSTHread 1cd0
我现在可以看到作为泄漏源的事件处理程序。我用 !do 来查看 事件处理程序的字段并获取
!do 01e19260
Name: System.EventHandler
MethodTable: 65129dc0
EEClass: 64ec39d0
Size: 32(0x20) bytes
(C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
MT Field Offset Type VT Attr Value Name
65130770 40000ff 4 System.Object 0 instance 01e19248 _target
6512ffc8 4000100 8 ...ection.MethodBase 0 instance 00000000 _methodBase
6513341c 4000101 c System.IntPtr 1 instance 0040C060 _methodPtr
6513341c 4000102 10 System.IntPtr 1 instance 00000000 _methodPtrAux
65130770 400010c 14 System.Object 0 instance 00000000 _invocationList
6513341c 400010d 18 System.IntPtr 1 instance 00000000 _invocationCount
所以现在我可以看到指向没有被分离的方法的指针
0040C060 _methodPtr
但我如何获得该方法的名称?
【问题讨论】:
-
请参阅我对这个问题的回答,了解如何获取 _methodPtr 指向的 stackoverflow.com/questions/3668642/…
-
哇,这是对调试检查的非常透彻的解释。赞成花时间发布一个详细的例子——它将来可能会被其他人使用。我会收藏这个。
标签: c# memory-leaks