關於使用WinDebug檢視執行緒死鎖問題

2021-07-03 18:33:31 字數 4186 閱讀 9813

最近專案接近尾聲,不過專案到了測試的時候大問題來了,偶爾介面直接卡死以至於後續無法測試,初步懷疑是**死鎖了,由於自己對windebug不是很熟悉,只知道windebug有查詢記憶體洩露問題、執行緒死鎖等相關功能,於是吩咐下面的人用windebug去查詢問題,索性網路資源比較多,通過一番調研找到了windebug死鎖查詢的解決方法,不過作為專案開發經理,遇到死鎖的事應該能夠在其他同時不能解決的時候也能提供相應的幫助是理所當然的,於是帶著這種心態去學習了windebug查詢死鎖的方法,總結如下:

死鎖,成立的條件就是:

(1)起碼有兩把鎖以上,假如僅有兩把鎖,且為鎖a和鎖b;

(2)執行緒1已經拿了一把鎖a然後還想去拿鎖b;執行緒2已經拿了一把鎖b然後還想去拿鎖a;

(3)沒有拿到另一把鎖不強行釋放自己獲取的鎖;

於是,死鎖來了~

實現所有的例項:

(1)初始化兩把鎖a和b,啟動兩個執行緒(可以乙個主線程和乙個子執行緒);

(2)第乙個執行緒已經拿了鎖a,第二個執行緒已經拿了鎖b,第一線程嘗試去拿鎖b,第二線程嘗試去拿鎖a;

基於以上思想,我寫了乙個demon,出現了死鎖情況,然後使用windebug查詢死鎖情況,方法介紹如下:

(1)啟用應用程式的使用者堆疊功能-我使用windebug開始沒有啟用導致windebug繫結程序失敗;

方法使用windebug目錄下的gflags.exe:開啟命令列,進入windebug目錄執行:gflag.exe /i  除錯exe的全路徑 +ust 

然後回車,ust 就是 user stack使用者堆疊;

(2)開啟windebug然後選擇file-->attach to process 附加到需要除錯的程序exe;

如果需要檢視所有執行緒堆疊那麼在命令視窗輸入:~*kv

輸出如下所有執行緒堆疊:

此時能開啟所有執行緒的堆疊,如果需要看某一線程的堆疊,則輸入*1kv也就是列印執行緒1的堆疊;從所有執行緒的堆疊中我們可以看到各個執行緒的堆疊資訊,如果此時有堆疊鎖,一般都在棧頂會有api呼叫:ntdll!rtlpwaitoncriticalsection,也就是找到所有的該api呼叫我們就可以找到對應的死鎖執行緒資訊;

0  id: 11264.10f20

id: 11264.1175c suspend: 1 teb: 7ef9f000 unfrozen

childebp retaddr  args to child              

0580fcf8 7776fb96 64db414e 00000000 00000000 ntdll!dbgbreakpoint (fpo: [0,0,0])

0580fd28 76e0336a 00000000 0580fd74 777092b2 ntdll!dbguiremotebreakin+0x3c (fpo: [non-fpo])

0580fd34 777092b2 00000000 64db4112 00000000 kernel32!basethreadinitthunk+0xe (fpo: [non-fpo])

0580fd74 77709285 7776fb5a 00000000 00000000 ntdll!__rtluserthreadstart+0x70 (fpo: [non-fpo])

0580fd8c 00000000 7776fb5a 00000000 00000000 ntdll!_rtluserthreadstart+0x1b (fpo: [non-fpo])

由此可以看出總共有0-3號4個執行緒,綠色的表示執行緒執行緒索引號,藍色的表示執行緒的位址(11264.1175c中11264位執行緒id,1175c為執行緒位址),當然所有執行緒列印出來乙個乙個找鎖不容易觀察到死鎖,為了能直接列印程序中線程之間的死鎖,直接使用如下命令

首先,檢視程序中所有的鎖,輸入命令 :  !locks,如下:

0:003>!locks

此時列印出程序中所有的鎖資訊:

critsec lockdemon!g_locka+0 at 0161cd80

waiterwoken        no

lockcount          1

recursioncount     1

owningthread       9238

entrycount         0

contentioncount    1

*** locked

critsec lockdemon!g_lockb+0 at 0161cd68

waiterwoken        no

lockcount          1

recursioncount     1

owningthread       10f20

entrycount         0

contentioncount    1

*** locked

第一把鎖位址為0161cd80,lockcount表示占有該鎖的數目,recursioncount  表示擁有者執行緒進入該鎖的次數(進入拿到鎖後還可以進入多次),owningthread 擁有者執行緒為9238,也就是說0161cd80鎖被位址為9238執行緒占用,也就是執行緒索引號為2 ,執行緒id為11264執行緒位址為

9238

的執行緒已經拿了鎖0161cd80,卻在等待鎖 

0161cd68 

第二把鎖位址為0161cd68,lockcount表示占有該鎖的數目,recursioncount  表示擁有者執行緒進入該鎖的次數(進入拿到鎖後還可以進入多次),owningthread 擁有者執行緒為10f20,也就是說0161cd68鎖被位址為10f20執行緒占用,也就是執行緒索引號為0 ,執行緒id為11264執行緒位址為

10f20

的執行緒已經拿了鎖0161cd68,卻在等待鎖 

0161cd80

這樣死鎖就這麼被確定下來,執行緒0和執行緒2互鎖!

堆疊列資訊解釋如下:

2  id: 11264.9238 suspend: 1 teb: 7efd7000 unfrozen

childebp retaddr  args to child              

064efbf4 77709e2e 00000120 00000000 00000000 ntdll!zwwaitforsingleobject+0x15 (fpo: [3,0,0])

064efc58 77709d12 00000000 00000000 005819a0 ntdll!rtlpwaitoncriticalsection+0x13e (fpo: [non-fpo])

064efc80 01140f78 0161cd68 00000000 00000000 ntdll!rtlentercriticalsection+0x150 (fpo: [non-fpo])

064efd58 014c22e3 003ef808 c5b8f482 00000000 lockdemon!myfunc+0x48 (fpo: [non-fpo]) (conv: stdcall) [e:\work\c++\test\lockdemon\lockdemon\lockdemondlg.cpp @ 79]

064efd94 014c2254 00000000 064efdac 76e0336a lockdemon!_callthreadstartex+0x53 (conv: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c @ 348]

064efda0 76e0336a 005819a0 064efdec 777092b2 lockdemon!_threadstartex+0xa4 (conv: stdcall) [f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c @ 331]

064efdac 777092b2 005819a0 6715418a 00000000 kernel32!basethreadinitthunk+0xe (fpo: [non-fpo])

064efdec 77709285 014c21b0 005819a0 00000000 ntdll!__rtluserthreadstart+0x70 (fpo: [non-fpo])

064efe04 00000000 014c21b0 005819a0 00000000 ntdll!_rtluserthreadstart+0x1b (fpo: [non-fpo])

第三列也就是後面api的第乙個引數,對於api 即rtlentercriticalsection的第乙個引數也就是第三列就是鎖的位址,也就是執行緒id為2(執行緒位址為0x9238)的執行緒在等鎖0x0161cd68

關於懸線法

懸線法的模板題,下面主要講懸線法 懸線法思路 懸線的定義,就是一條豎線,這條豎線要滿足上端點在整個矩形上邊界或者是乙個障礙點。然後以這條懸線進行左右移動,直到移至障礙點或者是矩陣邊界,進而確定這條懸線所在的極大矩陣。具體方法 先預處理 用陣列l,r記錄某點向左和向右能到達的最遠點的縱座標。用陣列up...

關於recyclerView分隔線取巧

首先吹一波,最近在使用recyclerview做專案.感覺挺好用的,個人推薦大家一起用 關於分隔線問題可以去看這個部落格 這裡我就開始說我取巧的方法了 話不多說 直接上碼 子布局的xml 直接在你recyclerview子布局裡面設定android background color font whi...

關於直線,V形線,Z形線,M形線分割平面的總結

一 n條直線分割平面 假設,x條線能將平面分為f x 份,這對於份f n 第n條線,和其他n 1條線都有交點時,增加量最大,為n 則 f n f n 1 n 有f 0 1 得到 n 條直線分割平面的數量最大為 f n n n 1 2 1 二.v 形線分割平面 對於 v 我們可以把他們當成兩條相交直線...