2012-09-25 35 views
24

我有一個計算開銷很大的多線程C#應用程序,運行30-90分鐘後似乎一直崩潰。它給出的錯誤是我在JIT/CLR中發現了一個錯誤 - 現在我該如何調試或複製它?

運行時遇到致命錯誤。錯誤的地址是0xec37ebae,線程0xbcc。錯誤代碼是0xc0000005。此錯誤可能是CLR中的錯誤,也可能是用戶代碼中不安全或不可驗證的部分。此錯誤的常見來源包括COM-interop或PInvoke的用戶編組錯誤,這可能會破壞堆棧。

(0000005是Access Violation錯誤代碼)

我的應用程序不調用任何本地代碼,或使用任何不安全塊,甚至是任何非CLS兼容類型,如uint。事實上,代碼調試器說行導致崩潰的原因是

overallLength += distanceTravelled; 

如果雙方的值類型的double


考慮到這一切,我相信碰撞必定是由於錯誤在編譯器或CLR或JIT中。我想弄清楚是什麼原因造成的,或者至少寫一個更小的複製品發送到微軟,但我不知道從哪裏開始。我從來沒有查看CIL二進制文件,或編譯的JIT輸出,或本地堆棧跟蹤(在崩潰時沒有託管堆棧跟蹤),所以我不知道如何。我甚至無法弄清楚如何在崩潰時查看所有變量的狀態(不幸的是,在託管異常之後,VS不會告訴我它喜歡它,並將它們輸出到控制檯/文件會減慢該應用程序1000倍,這顯然不是一種選擇)

那麼,我該如何去調試呢?


[編輯]下,VS 2010 SP1編譯,運行最新版本的.NET 4.0客戶端配置文件的。顯然,這是」。NET 4.0℃/ .NET 4.0E,.NET CLR 1.1.4322"

+0

您確定這不是您計算機上的內存問題嗎?我發現當指針被破壞並設置爲無效的內存位置時,其他程序中會出現相同的錯誤代碼。 – Matthew

+0

@Matthew:我將運行一些內存測試,並嘗試在另一臺機器上重現它。但我懷疑 - 這個程序不是非常耗費內存,我也沒有任何其他程序的問題。而且,它總是在同一條線上崩潰。 –

+0

我對CLR並不熟悉,但在Sun JVM上有一個標誌,它會記錄所有已編譯的方法 - 如果您可以確定(1)JIT是否被調用,以及(2)多長時間事故發生後。可能有一個工具可以讓你檢查內存映射,找出在那個地址加載了什麼(甚至是否在代碼塊中)。 – parsifal

回答

22

我想弄清楚是什麼導致了它,或者至少寫了一個較小的複製品發送到微軟,但我不知道從哪裏開始。

「較小的複製」在這裏聽起來確實是一個好主意......即使「較小」也不意味着「更快複製」。

在你開始之前,嘗試在另一臺機器上重現錯誤。如果你不能在另一臺機器上覆制它,這就暗示了一組完全不同的測試 - 硬件,安裝等。

另外,檢查你是否是最新版本的一切。如果花費數天的時間來調試(恐怕很可能),然後最終得到「是的,我們知道這個 - 它是.NET 4中的一個錯誤,它已經在.NET 4.5中修復了」 「 例如。如果你能重現上的各種框架的版本,那會更好:)

接下來,切出在程序的一切,您可以:

  • 它有一個用戶界面呢?如果可能的話,刪除它。
  • 它使用數據庫嗎?看看你是否可以刪除所有的數據庫訪問權限:絕對是以後不用的任何輸出,也是理想的輸入。如果您可以在應用程序中對輸入進行硬編碼,那將是理想的選擇 - 但如果不是這樣,文件比數據庫訪問更容易進行復制。
  • 它對數據敏感嗎?再說一遍,在不瞭解應用程序的情況下,很難知道這是否有用,但假設它正在處理大量數據,是否可以使用二進制搜索來查找導致此問題的相對較少的數據量?
  • 是不是要多線程?如果你可以刪除所有的線程,顯然這可能會花費更長的時間來重現問題 - 但它仍然會發生嗎?嘗試刪除一些業務邏輯:如果您的應用程序已適當組件化,則可以首先創建存根實現,然後簡單地刪除調用,從而虛構出整個重要組件。

所有這些將逐漸減小應用程序的大小,直到它更易於管理。在每一步中,您都需要再次運行應用程序,直到它崩潰或者您確信它不會崩潰。如果你有很多提供給您的機器,應該幫助的......

+4

只是一個更新:它出現[ponsfonze發現我的問題](http://stackoverflow.com/a/14001081/238419)。當然,這是一個在.Net 4.5中修復的問題......我應該聽你的! –

4

我的應用程序不調用任何本地代碼,或使用任何不安全塊,或者 甚至任何不符合CLS類型,比如UINT

你可能會這樣想,但是線程化,通過信號量同步,互斥鎖它的任何處理都是本地的。 .net是操作系統上的一層,.net本身不支持多線程應用程序的純粹clr代碼,這是因爲OS已經做到了。

這很可能是線程同步錯誤。可能有多個線程試圖訪問共享資源,如clr邊界外的文件等。

你可能認爲你沒有訪問com等,但是當你調用某些API如獲取桌面文件夾路徑等時,它通過shell com API調用。

,可以有以下兩種選擇,

  1. 發佈您的代碼,以便我們可以查看瓶頸
  2. 使用.NET並行線程框架,其中包括各種需要CPU密集型操作的算法重新設計你的應用程序。

隨着集合的增長和操作在其他線程干擾之前無法執行,很可能程序在一段時間後失敗。例如,生產者消費者問題,你不會注意到,直到製片人的任何問題都會變得更慢或無法完成在消費者面前踢它的操作。

的Bug CLR是罕見的,因爲CLR是非常穩定的。但寫得不好的代碼可能會導致錯誤在clr中出現錯誤。 Clr不能也不會檢測到錯誤是在你的代碼還是在clr本身。

+1

*「使用.net並行線程框架重新設計您的應用程序」* - 該**是**它使用的內容。 –

+0

如果您將發佈代碼的一些內部特性,那麼我們可以指導更多內容。 –

+0

我強烈建議先看看多線程問題。這很可能會導致內存損壞。這實際上會爲複製創造一個良好的起點,創建一個多線程的應用程序來執行大量常用計算。 – MikeKulls

1
+0

有dumpfile,它不是一個硬件問題 - 我可以在其他幾臺機器上重現它。 –

6

下載Debug Diagnostic Tool v1.2

  1. 運行程序
  2. 添加規則 「撞車」
  3. 選擇 「特定處理」
  4. on page 高級配置如果你知道它發生了哪個異常或者只是離開這個頁面,就會設置你的異常
  5. 設置用戶轉儲位置

現在等待進程崩潰,日誌文件被創建DebugDiag資料。現在激活標籤高級分析,選擇頂部列表中的崩潰/懸掛分析器並在下部列表中選擇轉儲文件,然後點擊開始分析。這會爲你生成html報告。希望您在該報告中找到有用的信息。如果分析有問題,請在某處上傳html報告,並在此處放置網址,以便我們專注於此。

0

我會建議你通過http://support.microsoft.com立即打開支持的情況下,因爲支撐傢伙可以告訴你如何收集必要的信息。

一般來說,就像@ paulsm4和@psulek所說的那樣,您可以使用WinDbg或調試診斷來捕獲進程的崩潰轉儲,並在其中嵌入所有必要的信息。但是,如果這是您第一次使用這些工具,那麼您可能會感到困惑。 Microsoft支持團隊可以爲您提供一步一步的指導,或者他們甚至可以設置Live Meeting會話來捕獲數據,因爲程序經常崩潰。

一旦你熟悉的工具,將來你可以執行類似的故障排除更容易,

http://blogs.msdn.com/b/lexli/archive/2009/08/23/when-the-application-program-crashes-on-windows.aspx

順便說一句,這是言之尚早,「我發現了一個錯誤」。儘管在程序中顯然無法找到對本機代碼的依賴,但它仍然可能依賴於本機代碼。在進一步調查問題之前,我們不應該得出結論。

10

TL;博士確保您編譯到.NET 4.5


這聽起來很像同樣的錯誤發現here。來自MSDN page

當垃圾收集器釋放和壓縮內存時可能會遇到此錯誤。當啓用Concurrent Garbage Collection並且發生前臺垃圾收集和後臺垃圾收集的某種組合時,可能會發生此錯誤。當這種情況發生時,你會看到一遍又一遍的相同的調用堆棧。在堆上你會看到一個空閒對象,在它結束之前你會看到另一個空閒對象破壞堆。

的修復程序是編譯到.NET 4.5。如果由於某種原因,你不能做到這一點,你也disable concurrent garbage collectionapp.config文件禁用gcConcurrent可以:

<configuration> 
    <runtime> 
     <gcConcurrent enabled="false"/> 
    </runtime> 
</configuration> 

或者只是編譯爲x86

相關問題