我想在我的应用程序中发现内存泄漏。 我会尝试查找没有安装软件或扩展程序的漏洞。
关注此链接
我试图建立自己的课程。
代码在这里:
''' <summary>
''' Use: lanch instance of the class
''' - Friend memorytest As New MemoryLeakTest(MemoryLeakTest.memorySize.MBytes)
''' Parameters:
''' - MemorySize (MBytes, KBytes, Bytes)
''' - AlertSize (set Alert to True if the increment of the new memory usage it's >)
'''
''' And then, to record the memory usage of a step
''' - memorytest.NewStep("abc")
'''
''' To record and get the memory usage of every step:
''' - PrintMethod(memorytest.NewStep("abc").ToString)
'''
''' To record a step and get only results with an Increment of the Memory used > initial alertSize setting:
''' - If memoryTest.NewStepConditioned("abc") Then PrintMethod(memoryTest.LastStep)
'''
''' To get the sum of all Memory increments by step:
''' - PrintMethod(memorytest.GetMemoryUsedByStep("abc"))
''' </summary>
''' <remarks></remarks>
Friend Class MemoryLeakTest
Sub New(Optional ByVal newMemorySize As memorySize = memorySize.KBytes, Optional ByVal newAlertSize As Integer = 0)
_memorySize = newMemorySize
_alertSize = newAlertSize
End Sub
Private _memorySize As memorySize
Private _alertSize As Integer
Private _Priority As Integer
Private _Id As Integer
Private _Title As String
Private _MaxWorkingSet As IntPtr
Private _MinWorkingSet As IntPtr
Private _ProcessName As String
Private _StartInfo As System.Diagnostics.ProcessStartInfo
Private _PriorityClass As System.Diagnostics.ProcessPriorityClass
Private _MemorySteps As New List(Of MemoryStep)
Friend Function NewStep(ByVal _Step As String) As String
CallGC()
CheckMemoryStep(_Step)
'CallGC()
Return _MemorySteps(_MemorySteps.Count - 1).ToString
End Function
Friend Function NewStepConditioned(ByVal _Step As String) As Boolean
CallGC()
CheckMemoryStep(_Step)
'CallGC()
Return _MemorySteps(_MemorySteps.Count - 1).Alert
End Function
Friend Function LastStep() As String
Return _MemorySteps(_MemorySteps.Count - 1).ToString
End Function
Friend Function GetMemoryUsedByStep(ByVal NewStep As String) As String
Dim MemoryUsed As List(Of MemoryStep) = _MemorySteps.FindAll(Function(x) x._step = NewStep)
Return MemoryUsed.Sum(Function(x) x._inc_WorkingSet).ToString & " " & _memorySize.ToString
End Function
Friend Sub CallGC()
GC.Collect()
GC.WaitForPendingFinalizers()
'GC.Collect()
End Sub
Friend Sub CheckMemoryStep(ByVal newStep As String)
Using cp As Process = Process.GetCurrentProcess
If IsNothing(_StartInfo) Then
_Priority = cp.BasePriority
_Id = cp.Id
_Title = cp.MainWindowTitle
_MaxWorkingSet = cp.MaxWorkingSet
_MinWorkingSet = cp.MinWorkingSet
_PriorityClass = cp.PriorityClass
_ProcessName = cp.ProcessName
_StartInfo = cp.StartInfo
_MemorySteps.Add(New MemoryStep(newStep, cp, _memorySize, _alertSize))
Else
_MemorySteps.Add(New MemoryStep(newStep, cp, _memorySize, _alertSize, _MemorySteps(_MemorySteps.Count - 1)))
End If
End Using
End Sub
Friend Class MemoryStep
Sub New(ByVal newStep As String, ByVal cp As System.Diagnostics.Process, ByVal memSize As memorySize, ByVal alertSize As Integer, Optional ByVal oldStep As MemoryStep = Nothing)
_memorySize = memSize
_step = newStep
_NonPagedSystemMemory = CLng(cp.NonpagedSystemMemorySize64 / memSize)
_PagedMemory = CLng(cp.PagedMemorySize64 / memSize)
_PagedSystemMemory = CLng(cp.PagedSystemMemorySize64 / memSize)
_PeakPagedMemory = CLng(cp.PeakPagedMemorySize64 / memSize)
_PeakVirtualMemory = CLng(cp.PeakVirtualMemorySize64 / memSize)
_PeakWorkingSet = CLng(cp.PeakWorkingSet64 / memSize)
_PrivateMemory = CLng(cp.PrivateMemorySize64 / memSize)
_VirtualMemory = CLng(cp.VirtualMemorySize64 / memSize)
_WorkingSet = CLng(cp.WorkingSet64 / memSize)
If Not IsNothing(oldStep) Then
With oldStep
_inc_NonPagedSystemMemory = _NonPagedSystemMemory - ._NonPagedSystemMemory
_inc_PagedMemory = _PagedMemory - ._PagedMemory
_inc_PagedSystemMemory = _PagedSystemMemory - ._PagedSystemMemory
_inc_PeakPagedMemory = _PeakPagedMemory - ._PeakPagedMemory
_inc_PeakVirtualMemory = _PeakVirtualMemory - ._inc_PeakVirtualMemory
_inc_PeakWorkingSet = _PeakWorkingSet - ._PeakWorkingSet
_inc_PrivateMemory = _PrivateMemory - ._PrivateMemory
_inc_VirtualMemory = _VirtualMemory - ._VirtualMemory
_inc_WorkingSet = _WorkingSet - ._WorkingSet
End With
End If
If _inc_WorkingSet > alertSize Then
Alert = True
End If
End Sub
Private _NonPagedSystemMemory As Long
Private _PagedMemory As Long
Private _PagedSystemMemory As Long
Private _PeakPagedMemory As Long
Private _PeakVirtualMemory As Long
Private _PeakWorkingSet As Long
Private _PrivateMemory As Long
Private _VirtualMemory As Long
Private _WorkingSet As Long
Private _memorySize As memorySize
Private _inc_NonPagedSystemMemory As Long
Private _inc_PagedMemory As Long
Private _inc_PagedSystemMemory As Long
Private _inc_PeakPagedMemory As Long
Private _inc_PeakVirtualMemory As Long
Private _inc_PeakWorkingSet As Long
Private _inc_PrivateMemory As Long
Private _inc_VirtualMemory As Long
Friend _inc_WorkingSet As Long
Friend _step As String
Friend Alert As Boolean = False
Public Overrides Function ToString() As String
ToString = _step & vbTab & "memory usage: " & _WorkingSet.ToString & " " & _memorySize.ToString
If _inc_WorkingSet < 0 Then
ToString += " (- " & -_inc_WorkingSet.ToString & " " & _memorySize.ToString & ")"
Else
ToString += " (+ " & _inc_WorkingSet.ToString & " " & _memorySize.ToString & ")"
End If
Return ToString
End Function
End Class
Enum memorySize
MBytes = 1024000
KBytes = 1024
[Bytes] = 1
End Enum
End Class
此类的使用应为:
Class Test
Friend memorytest As New MemoryLeakTest(MemoryLeakTest.memorySize.MBytes)
Sub RunTest()
memorytest.NewStep("Start")
Method_1()
WriteToTextBox(memorytest.NewStep("Method_1").ToString)
Method_2()
WriteToTextBox(memorytest.NewStep("Method_2").ToString)
Method_3()
If memoryTest.NewStepConditioned("Method_3") Then WriteToTextBox(memoryTest.LastStep)
End Sub
Private Sub Method_1()
'Do something
End Sub
Private Sub Method_2()
'Do something
End Sub
Private Function Method_3()
'Do something
End Function
Private Sub WriteToTextBox(ByVal msg As String)
With TextBox1
.SelectionStart = .Text.Length
.SelectedText = VbCrlf & Date.Now.ToLongTimeString & Chr(9) & msg
End With
End Sub
End Class
在我看来效果很好,但是由于对GC的深入了解需要我目前没有的很多时间,因此我会向社区询问此类在创建内存时是否可以有效地发现内存泄漏
答案 0 :(得分:0)
发现mo漏并不容易。您应该重新考虑安装第三方软件来检测它们。或在调试时使用Visual Studio诊断选项卡。
GC很慢,因为它必须进行大量内存检查。此类仅告诉您是否可能存在一些泄漏。但这不会告诉您在哪里可以找到它们。
答案 1 :(得分:0)
由于我没有收到很多答案,所以我自己回答。
我的问题是我有一个程序,该程序以25 MB的内存使用开始,随着时间的推移它达到1.5 GB,然后由于“内存不足异常”而崩溃。
我有以下建议:
通过我在示例中发布的课程,我轻松快捷地找到了导致泄漏的过程。
在这些过程中,我确定了实现iDisposable所需的类以及应重写的代码部分。
那时候我以这种模式解决了:
正确实施iDisposable:在此处提供简要正确的解释 Implementing IDisposable
使用不同的构造函数实例化实例来优化Class代码。
尤其是我替换了此类代码
Class MyClass()
Sub New()
End Sub
Friend Inst_of_my_2nd_class As New My2ndClass()
Friend Inst_of_my_3rd_class As New My3rdClass()
Friend Inst_of_my_4th_class As New My4thClass()
End Class
使用此功能(注意。我不太清楚有关Dispose实例的代码,对我来说似乎效果很好)
Class MyClass()
Implements iDisposable
Sub New(ByVal ... As some)
Inst_of_my_2nd_class = New My2ndClass()
End Sub
Sub New(ByVal ... As someother)
Inst_of_my_3rd_class = New My3rdClass()
End Sub
Sub New(ByVal ... As someotherelse)
Inst_of_my_4th_class = New My4thClass()
End Sub
Friend Inst_of_my_2nd_class As My2ndClass()
Friend Inst_of_my_3rd_class As My3rdClass()
Friend Inst_of_my_4th_class As My4thClass()
#Region "IDisposable Support"
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
' what to put here: thanks to https://stackoverflow.com/questions/19895856/implementing-idisposable/19896116#19896116
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' what to put here: thanks to https://stackoverflow.com/questions/19895856/implementing-idisposable/19896116#19896116
If Not IsNothing(Inst_of_my_2nd_class) Then
Inst_of_my_2nd_class.Dispose()
Inst_of_my_2nd_class = Nothing
End If
If Not IsNothing(Inst_of_my_3rd_class) Then
Inst_of_my_3rd_class.Dispose()
Inst_of_my_3rd_class = Nothing
End If
If Not IsNothing(Inst_of_my_4th_class) Then
Inst_of_my_4th_class.Dispose()
Inst_of_my_4th_class = Nothing
End If
' TODO: set large fields to null.
' what to put here: thanks to https://stackoverflow.com/questions/19895856/implementing-idisposable/19896116#19896116
End If
Me.disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class