我有一个用VB.NET编写的相当大的应用程序,它似乎遭受了这种或那种类型的内存泄漏。每天几次,我有这个应用程序的实例崩溃(看似随机,但总是在使用了近一天)。我已经搜索并阅读了许多论坛,甚至在Stack Overflow上询问了有关此特定问题的问题。我所确定的是,这与内存泄漏有关,通常指向超过10,000的句柄或超出限制的对象。
我已经下载了内存专业文件管理器并用它来定位和修复程序中的几个内存泄漏,但这似乎并没有减缓每日崩溃次数。我的程序使用全局错误捕获器来记录这些事件并将有关它们的信息存储在数据库中。我现在有大约2个月的数据,但错误信息并没有真正帮助我指出任何方向。我最近添加了这个全局错误捕获器记录应用程序具有的句柄的能力,并且到目前为止远远低于10,000句柄阈值。通常不到1000。
长话短说,我的问题是这个。有没有办法记录GDI对象计数,以便我可以确定是否导致我的程序崩溃?是否有其他对象'这可能导致内存泄漏和崩溃除了这两个,我可以记录那些如何?
我尽可能多地尝试阅读,但我无法很好地掌握这一点,所以我很欣赏你能给我的方向。似乎这些类型的问题困扰着很多程序。希望有人可以帮助我,这可以在将来帮助其他人。
有关我的计划和环境的更多信息。它主要运行在Windows 7 64位机器上(虽然存在一些vista和XP机器),它运行在.NET 4.0框架上。该项目由几百个表单,类和自定义控件组成(专门为此项目构建)。我使用.NET内存分析器4.6来检查内存泄漏。我在计算机上运行了我认为最耗费资源的操作超过一个小时(打开并随后关闭了很多屏幕,处理了大量的数据等等),同时观察任务中的资源管理器(句柄,线程,用户对象和GDI对象),但没有一个超过1000。
以下是崩溃事件中其中一个日志的副本:
Loaded Assembly: GlobalFuncs, Version=1.0.3391.14822, Culture=neutral, PublicKeyToken=null
Loaded Assembly: Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Loaded Assembly: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly: MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d
Loaded Assembly: SQL Database, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Loaded Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly: System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Loaded Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly: System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly: System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Loaded Assembly: System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Loaded Assembly: System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Loaded Assembly: System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly: System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly: System.Speech, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
Loaded Assembly: System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
OS Name: Microsoft Windows 7 Professional
OS Version: 6.1.7601.65536
OS Platform: x64
Physical Memory: 1.91GB / 3.90GB (Free / Total)
Virtual Memory: 1.66GB / 2.00GB (Free / Total)
Error Output:
System.ComponentModel.Win32Exception (0x80004005): Error creating window handle.
at System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.TextBoxBase.CreateHandle()
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.RichTextBox.get_TextLength()
at System.Windows.Forms.TextBoxBase.AdjustSelectionStartAndEnd(Int32 selStart, Int32 selLength, Int32& start, Int32& end, Int32 textLen)
at System.Windows.Forms.TextBoxBase.GetSelectionStartAndLength(Int32& start, Int32& length)
at System.Windows.Forms.TextBoxBase.AppendText(String text)
at SWOT.My.MyApplication.ShowDebugOutput(Exception ex)
at SWOT.My.MyApplication.app_ThreadException(Object sender, ThreadExceptionEventArgs e)
at System.Windows.Forms.Application.ThreadContext.OnThreadException(Exception t)
at System.Windows.Forms.Control.WndProcException(Exception e)
at System.Windows.Forms.Control.ControlNativeWindow.OnThreadException(Exception e)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
我唯一的另一个是我的全局错误捕获器在尝试加载时崩溃,因为它无法再创建句柄而且我不知何故丢失了这些信息。但是它没有崩溃并且能够记录句柄计数的时间非常低(低于1000)。在程序可以记录高句柄数之前,垃圾收集器是否在崩溃后立即释放了大量资源?我对我的数据感到有些迷茫和困惑。
答案 0 :(得分:0)
我有相同的错误消息,并且不确定到底出了什么问题!,但我仍然想分享它是如何解决的......
我没有做任何特别的事情,但正如Scott所说,表单是通过创建一个新实例和Form.show()方法调用当从主窗体中单击一个按钮,我做了什么,而不是通过单击事件打开窗体我只是给表单导致错误直接作为启动表单并尝试运行..表单没有加载也没有错误消息!我回去并将启动表单再次更改回主表单并运行,然后当我点击时它是一个魔术在加载表单的按钮上没有任何错误消息!!!。
不知道背后发生了什么变化,但现在一切都很好......
答案 1 :(得分:-1)
基于错误输出声明你有相当多的内存(超过1GB)并且错误消息是"错误创建窗口句柄"这一事实,我怀疑你的应用程序遇到了问题没有释放句柄,而不是释放内存。不释放句柄的最可能原因是使用P / Invoke调用。您只需搜索Declare
和DllImport
的代码,看看您是否实际使用了任何P / Invoke函数。如果您是,您需要对您调用的每个函数进行详细审核,如果它返回任何句柄(通过IntPtr
或SafeHandle-derived classes)。如果这些调用中的任何一个创建了一个Handle - 尤其是一个窗口句柄(通常缩写为hWnd),那么你需要验证你的代码是否释放了hWnd。
如果您没有使用任何DllImport / P / Invoke代码,那么很可能您是通过托管代码间接调用一个代码,例如创建一个新的System.Windows.Forms.Form
或System.Windows.Forms.Control
派生类(它也会创建一个窗口句柄)而不是不调用Close或Dispose。还有其他东西可以创建句柄,但会想到这些。