VB中的内存泄漏

问题描述:

我们注意到有关VB中内存管理的一个有趣的问题,我们不了解.如果有人可以帮助我们,请这样做.

We noticed one interesting issue regarding memory management in VB that we do not understand. If anyone could help us with this one, please do.

我们有一个简单的类,只有一个事件.我们创建并销毁了5000个此类的实例,在运行测试之前,我们先读取了进程的内存使用情况.最后,我们强制GC并再次检查内存.我们注意到的是,我们的内存不断增长.我们在C#中进行了相同的示例,但没有遇到此问题.现在是有线点.如果我们省略类中的事件声明,则将按预期清除内存.是否有人知道原因,以及完成此课程的正确方法是什么?

We have a simple class with one single event. We create and destroy 5000 instances of this class and before we run a test we read the process memory usage. At the end we force GC and check the memory again.What we noticed is, that we have a constant memory growing. We did the same sample in C# and we did not run into this issue. Now here is the wired point. If we omit event declaration from class the memory will be cleaned as we expected. Does any one know why, and what is the right way to finalize this class.

这是示例代码:

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim memorySize As Long
        memorySize = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64

        Console.Out.WriteLine(System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 / (1024.0 * 1024.0))
        For index As Integer = 1 To 5000
            Dim x As New TestClass()


            x = Nothing
            Me.Text = index.ToString()
        Next
        GC.Collect()
        Console.Out.WriteLine(System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 / (1024.0 * 1024.0))
        Console.Out.WriteLine("delta: " + ((System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 - memorySize) / (1024.0)).ToString() + " kb")

    End Sub
End Class

和测试班级:

Imports System.ComponentModel
Imports System.ComponentModel.Design.Serialization
Imports System.Xml
Imports System.Xml.XPath

Public Class TestClass

    Friend Event ForeColorChanged()

    Public Sub New()
    End Sub


    Protected Overrides Sub Finalize()
        MyBase.Finalize()
    End Sub

End Class

几次运行后的打印输出:

And the printout after several runs:

22,76953125
23,828125
delta: 2016 kb
24,08984375
24,0625
delta: 228 kb
24,4375
24,2109375
delta: 24 kb
24,58984375
24,83984375
delta: 384 kb
24,84375
24,890625
delta: 48 kb

您的代码没有编译,TestClass没有实现Dispose()方法.

Your code doesn't compile, TestClass doesn't implement the Dispose() method.

我可以猜到你在看什么. VB.NET编译器生成的Edit + Continue支持代码中存在一个已知的错误.它使用WeakReference来跟踪分配的事件处理程序,当您在不使用调试器的情况下运行代码时,该WR对象会泄漏.通过注释事件或运行代码的Release版本,检查是否可以解决问题.

I can guess what you are seeing though. There's a known bug in the Edit+Continue support code that the VB.NET compiler generates. It uses a WeakReference to track assigned event handlers, that WR object is leaked when you run your code without a debugger. Check if you can fix your problem by either commenting out the Event or by running the Release build of your code.

您无法交付项目的Debug版本,当那些泄漏的WeakReference对象消耗所有内存时,它将用OOM轰炸.仅发布Release版本.

You cannot ship the Debug build of your project, it will bomb with OOM when those leaked WeakReference objects consume all memory. Only ever ship the Release build.