为什么导致内存泄漏?

时间:2023-01-20 17:40:35

This is interesting. We've spent the last day attempting to patch a problem with the following (legacy) code that continues to grow its process size. This is done in Visual Studio 2003.

这是有趣的。我们花了最后一天尝试使用以下(遗留)代码修补问题,这些代码继续增加其流程大小。这是在Visual Studio 2003中完成的。

We have a form on which we display an image (from MemoryStream) and some text and a button. Nothing fancy. Looks something like this:

我们有一个表单,我们在其上显示一个图像(来自MemoryStream)和一些文本和一个按钮。没有什么花哨。看起来像这样:

  Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
    MyBase.OnLoad(e)
    Try
      m_lblWarning.Visible = False

      m_grpTitle.Text = m_StationInterface.ProcessToolTitle
      m_lblMessage.Text = m_StationInterface.ProcessToolMessage

      Dim objImage As MemoryStream
      Dim objwebClient As WebClient
      Dim sURL As String = Trim(m_StationInterface.ProcessToolPicLocation)

      objwebClient = New WebClient

      objImage = New MemoryStream(objwebClient.DownloadData(sURL))
      m_imgLiftingEye.Image = Image.FromStream(objImage)

      m_txtAcknowledge.Focus()
    Catch ex As Exception
      '*** This handles a picture that cannot be found without erroring'
      m_lblWarning.Visible = True
    End Try
  End Sub

This form is frequently closed and opened. Each time it is re-opened, the process memory usage grows by roughly 5mb. When the form is closed, it doesn't drop back down to its previous usage. The resources remain allocated for the unreferenced form. The form is rendered like this:

此表格经常关闭和打开。每次重新打开时,进程内存使用量大约增加5mb。当表单关闭时,它不会回退到之前的用法。资源仍然为未引用的表单分配。表单呈现如下:

      m_CJ5Form_PTOperatorAcknowlegement = New CJ5Form_PTOperatorAcknowlegement
      m_CJ5Form_PTOperatorAcknowlegement.stationInterface = m_StationInterface
      m_CJ5Form_PTOperatorAcknowlegement.Dock = DockStyle.Fill
      Me.Text = " Acknowledge Quality Alert"

      '*** Set the size of the form'
      Me.Location = New Point(30, 30)
      Me.Size = New Size(800, 700)

      Me.Controls.Add(m_CJ5Form_PTOperatorAcknowlegement)

The control is later removed from the form after closing:

关闭后,控件稍后将从表单中删除:

Me.Controls.Clear()

Now. We've tried very numerous things. We've discovered that Disposing does nothing, and, indeed, the IDisposable interface doesn't actually touch memory. If we don't create a new CJ5Form_PTOperatorAcknowledgement form each time, the process size does NOT grow. But loading a new image into that form still causes the process size to continually grow.

现在。我们尝试了很多东西。我们发现Disposing什么都不做,实际上,IDisposable接口实际上并没有触及内存。如果我们每次都不创建新的CJ5Form_PTOperatorAcknowledgement表单,则流程大小不会增长。但是将新图像加载到该表单中仍会导致进程大小不断增长。

Any suggestions would be appreciated.

任何建议,将不胜感激。

2 个解决方案

#1


You have to dispose of your WebClient object and any other managed unmanaged resources that may no longer be needed.

您必须处置WebClient对象以及可能不再需要的任何其他托管非托管资源。


objImage = New MemoryStream(objwebClient.DownloadData(sURL))
objwebClient.Dispose() ' add call to dispose

An even better way to code that would be to use a 'using' statement:

一种更好的代码方法是使用'using'语句:


using objwebClient as WebClient = New WebClient      
objImage = New MemoryStream(objwebClient.DownloadData(sURL))      
end using

For further information please search for 'Dispose' and 'IDisposable' pattern implementation on google and *.

有关详细信息,请在google和*上搜索“Dispose”和“IDisposable”模式实现。

One last hint: Don't use a memory stream if possible. Load the image directly from file unless you need to keep it in RAM.

最后一个提示:如果可能,请不要使用内存流。直接从文件加载图像,除非您需要将其保存在RAM中。

Edit

If I understand your code correctly perhaps something like this would work:

如果我正确理解你的代码,也许这样的东西会起作用:


Dim objImage As MemoryStream      
Dim objwebClient As WebClient      
Dim sURL As String = Trim(m_StationInterface.ProcessToolPicLocation)      
using objwebClient as WebClient = New WebClient      
  using objImage as MemoryStream = New MemoryStream(objwebClient.DownloadData(sURL))      
    m_imgLiftingEye.Image = Image.FromStream(objImage)
  end using
end using

#2


I don't know why specifically that is leaking, but I can recommend that you look at using the .NET Memory Profiler. If you run your application using that, it will give you a very good idea of what objects are not being disposed and help you troubleshoot why. It's got a free trial, but it's well worth the purchase.

我不知道为什么会泄漏,但我建议你看一下使用.NET Memory Profiler。如果您使用它运行应用程序,它将使您非常了解哪些对象未被处置,并帮助您解决原因。它有一个免费试用版,但值得购买。

#1


You have to dispose of your WebClient object and any other managed unmanaged resources that may no longer be needed.

您必须处置WebClient对象以及可能不再需要的任何其他托管非托管资源。


objImage = New MemoryStream(objwebClient.DownloadData(sURL))
objwebClient.Dispose() ' add call to dispose

An even better way to code that would be to use a 'using' statement:

一种更好的代码方法是使用'using'语句:


using objwebClient as WebClient = New WebClient      
objImage = New MemoryStream(objwebClient.DownloadData(sURL))      
end using

For further information please search for 'Dispose' and 'IDisposable' pattern implementation on google and *.

有关详细信息,请在google和*上搜索“Dispose”和“IDisposable”模式实现。

One last hint: Don't use a memory stream if possible. Load the image directly from file unless you need to keep it in RAM.

最后一个提示:如果可能,请不要使用内存流。直接从文件加载图像,除非您需要将其保存在RAM中。

Edit

If I understand your code correctly perhaps something like this would work:

如果我正确理解你的代码,也许这样的东西会起作用:


Dim objImage As MemoryStream      
Dim objwebClient As WebClient      
Dim sURL As String = Trim(m_StationInterface.ProcessToolPicLocation)      
using objwebClient as WebClient = New WebClient      
  using objImage as MemoryStream = New MemoryStream(objwebClient.DownloadData(sURL))      
    m_imgLiftingEye.Image = Image.FromStream(objImage)
  end using
end using

#2


I don't know why specifically that is leaking, but I can recommend that you look at using the .NET Memory Profiler. If you run your application using that, it will give you a very good idea of what objects are not being disposed and help you troubleshoot why. It's got a free trial, but it's well worth the purchase.

我不知道为什么会泄漏,但我建议你看一下使用.NET Memory Profiler。如果您使用它运行应用程序,它将使您非常了解哪些对象未被处置,并帮助您解决原因。它有一个免费试用版,但值得购买。