2009-10-01 54 views
2

在java調試掛起的應用程序很容易。您可以獲取應用程序的內存轉儲,並使用和使用eclipse jvm轉儲分析器查看線程的狀態以及每個線程被阻止的位置?如何調試掛起(死鎖)的C++中的多線程應用程序?

像這樣的東西存在的C + +?

+3

你在開發什麼環境? (Visual Studio,GNU/Linux) – Steven 2009-10-01 20:04:51

+0

如果您可以談論這兩種環境,那將會非常棒。 調試在兩種環境中都很有趣,也是一項挑戰。由於Windows沒有自動獲取核心,所以在Windows中更具挑戰性。人們可能有其他意見 – pankajt 2009-10-01 21:02:25

回答

3

你可以用C++做同樣的事情;迫使核心轉儲並在之後查看它。或者,如果您使用的是MSVC,您可以在運行時簡單地將調試器附加到應用程序中。點擊「打破所有」,並通過線索四處闖蕩。

+0

我應該說我給出的答案或多或少是正確的。 MSVC提供了一個非常簡單的界面來調試C++應用程序。 – pankajt 2009-10-01 21:06:07

1

某些平臺支持pstack

+0

pstack絕對是一種選擇,我經常錯過。 感謝提醒。 :) – pankajt 2009-10-01 20:06:38

0

我還沒有做到這一點,但我認爲你可以使用gdb來生成你的應用程序的核心,在它被掛起的時刻。

您可以嘗試使用gdb本身來調試此內核,並親自查看哪些線程被阻塞在哪裏?

以上是在linux平臺下可能的。不確定,如果Windows上的cygwin可以用於相同的目的。

0

當然,陳述(或其他輸出替代品)的策略性放置始終是一種選擇,但往往遠非理想。

如果用g ++編譯,用-g編譯並使用gdb。您可以附加到正在運行的進程(和源代碼),或者只需在調試器中運行該程序即可開始。然後看看堆棧。

在Windows中,只需暫停執行程序並查看堆棧。

-1
  1. 圖出通過阻塞線程#擁有1
  2. 圖出通過阻塞線程#2
  3. 擁有的臨界區的關鍵部分確定正確的順序的說關鍵部分收購
+1

你可能會告訴他不要在第一時間寫錯誤。 – Potatoswatter 2009-10-02 05:54:48

+0

對不起,如果我很矮,但那真的很重要 - 所有陷入僵局的球員都被困在犯罪現場!現在,如果他對這個平臺更具體,我可以給出更好的建議,如何做#1-2 ... – 2009-10-05 05:47:22

0

您可以用GDB在Linux系統上看到日線狀態

4

神奇的調用在gdb是:

線程所有的BT應用

運行的BT(回溯)命令爲所有線程。除非你完全清除了你的程序,否則你應該能夠看到每個函數的名字。

這適用於實時和驗屍(即針對核心運行gdb)調試。

+2

也被稱爲「t a bt」 – Potatoswatter 2009-10-02 05:53:45

2

在Windows本機應用程序中Windbg是我選擇的工具。如果可能的話,我會調試一個死鎖的進程,否則一個完整的進程內存轉儲通常會讓你在那裏。

我的方法是繪製一個wait graph記錄線程和資源之間的關係。我通常通過運行命令!locks來確定哪些線程在死鎖進程中保留了任何關鍵部分。

我然後開始通過選擇具有最高爭計數的關鍵部分(如果有死鎖會出現圖中的一個週期,因此它並沒有真正不管你從哪裏開始)繪製圖形等待。找到擁有的線程並在調試器中選擇它(命令允許您將線程ID與調試器使用的線程號相關聯,請使用〜***線程號*** s選擇線程並使用kbn以顯示其堆棧。如果進程陷入僵局那麼它可能會進行某種形式的切斷動作如找來電RtlEnterCriticalSection或WaitForSingleObject的等人。在死鎖情況下,這些電話通常可以使您識別正被另一個資源等待。這個信息添加到等待圖形和繼續下去,直到你要麼回你開始的地方。

如果你等待圖形跨越進程邊界你可能會發現你需要找到誰擁有另一個進程中的內核對象(這就是爲什麼我可以調試直播)。 sysinternals Process Explorer工具對此很有用。

一旦你已經確定死鎖參與者,那麼你需要穿上找出下一步去哪裏你的思維帽。這可能意味着改變資源獲取的順序(正如有人指出的那樣),但實際上並沒有一個通用的方法,它需要額外的關於應用程序設計的信息來理解如何去除等待圖中的循環依賴。

在某些情況下,循環可能不是問題的原因,例如,您的系統可能正在等待永遠不會到來的用戶輸入(提示任何曾看到MessageBox調用的進程作爲服務運行的進程) 。

當然還有更給它比這布提希望,這可能使你動身在正確的方向。