2017-09-29 40 views
0

我們在數百個客戶端中安裝了WinForms應用程序。在其中一些內存中,隨着時間的推移,內存使用率開始上升,顯然沒有理由,直到OutOfMemoryException最終被拋出。可能由於終結器線程故障導致的內存泄漏故障排除

我們使用DebugDiag集合和分析來試圖理解問題。我們得到了these warnings

所以,首先要看的是Finalizer線程,因爲有一個巨大的對象隊列(42K)準備好完成。這是它的調用堆棧怎麼看起來像在轉儲的時間:

ntdll!KiFastSystemCallRet 
ntdll!NtWaitForSingleObject+c 
KERNELBASE!WaitForSingleObjectEx+98 
kernel32!WaitForSingleObjectExImplementation+75 
clr!CLREventBase::Reset+17e 
clr!CLREventBase::Reset+1c6 
clr!CLREventBase::WaitEx+152 
clr!FinalizerThread::WaitForFinalizerEvent+38 
clr!FinalizerThread::FinalizerThreadWorker+5f 
clr!Thread::DoExtraWorkForFinalizer+1b1 
clr!Thread::DoExtraWorkForFinalizer+234 
clr!Thread::DoExtraWorkForFinalizer+5f8 
[[DebuggerU2MCatchHandlerFrame]] 
clr!ManagedThreadBase::FinalizerBase+33 
clr!FinalizerThread::FinalizerThreadStart+d4 
clr!Thread::intermediateThreadProc+55 
kernel32!BaseThreadInitThunk+e 
ntdll!__RtlUserThreadStart+70 
ntdll!_RtlUserThreadStart+1b 

同樣的過程,五個小時之後,由DebugDiag資料顯示的警告是these

因此,隨着準備完成的對象數量大幅增加,泄露的內存幾乎翻了一番。終結者線程調用棧與前一個相同。事實上,這個問題似乎存在於一個封閉的finalized線程中,使得GC無法擺脫未使用的對象。

事情是,我們不在我們的代碼中使用終結器。終結線程可能會做什麼阻塞操作?我們怎麼能夠發現是否有一個外部模塊負責這個,它是哪一個?

一些額外的信息:我們使用的是.NET Framework 4.0,而我們的應用程序是爲x86編譯的。這個問題更有可能在Windows 7+ SO中重現,而XP則似乎表現得更好。

任何幫助或暗示在哪裏看將不勝感激。

+0

它非常高,但終結器線程堆棧跟蹤完全正常。所使用的內存量也是如此,這看起來不像是一個隨時會遇到內存耗盡的程序。確保GC運行得足夠頻繁。 –

+0

我們正在談論5小時的執行。我們的應用程序預計將在沒有重啓的情況下運行數月,這就是OutOfMemory發生的時間。 – armarru

回答

1

它的價值: 我在幾年前有過類似的情況。當程序資源耗盡時,gdi錯誤是典型的錯誤。最後,我使用了Redgate的螞蟻(免費試用期)來發現許多對象被保存在內存中。我使用VB.NET,並且這是一個鮮爲人知的事實,即使用'withevents'聲明的變量需要在終結器中顯式設置爲無。同時傳遞和保持對其他對象的引用也是垃圾人沒有出現的潛在原因。在終結器中將這些引用設置爲空(空)有助於。在VB中,表單的終結器代碼位於設計器文件中:

'Form overrides dispose to clean up the component list. 
    <System.Diagnostics.DebuggerNonUserCode()> _ 
    Protected Overrides Sub Dispose(ByVal disposing As Boolean) 
     If disposing AndAlso components IsNot Nothing Then 
      components.Dispose() 
     End If 

     MyBase.Dispose(disposing) 
     If Me.DesignMode Then Exit Sub 

     If disposing Then 
      JCboKind.DataSource = Nothing 
      JCBOCondition.DataSource = Nothing 
      JCboQuality.DataSource = Nothing 
      JCboSafetyCategory.DataSource = Nothing 
      JcboSurfTreatment.DataSource = Nothing 
      JCboUnit.DataSource = Nothing 
     End If 
     ... 
+0

我們也在使用VB.NET,事實上這聽起來像是一個可能的原因。我們會檢查出來的。 – armarru

+0

無論我在哪裏,我都可以使用「使用...最終使用」構造(每個實現IDisposable的對象),即對話框,sqlconnections,sqlcommands,filestreams ... –