我在C++的关键部分遇到问题。我得到一个挂起的窗口,当我转储该进程时,我可以看到线程在关键部分上等待:
16 Id: b10.b88 Suspend: 1 Teb: 7ffae000 Unfrozen
ChildEBP RetAddr
0470f158 7c90df3c ntdll!KiFastSystemCallRet
0470f15c 7c91b22b ntdll!NtWaitForSingleObject+0xc
0470f1e4 7c901046 ntdll!RtlpWaitForCriticalSection+0x132
0470f1ec 0415647e ntdll!RtlEnterCriticalSection+0x46
生产线数据等均表示已进入特定的关键部分。唯一的问题是,没有其他线程显示此关键部分处于打开状态。 Windbg的!locks命令没有任何指示,转储关键部分表明它没有被锁定,如空所有者和-1结构中的-1 LockCount所示。
0:016> dt _RTL_CRITICAL_SECTION 42c2318
_RTL_CRITICAL_SECTION
+0x000 DebugInfo : 0x02c8b318 _RTL_CRITICAL_SECTION_DEBUG
+0x004 LockCount : -1
+0x008 RecursionCount : -1
+0x00c OwningThread : (null)
+0x010 LockSemaphore : 0x00000340
+0x014 SpinCount : 0
0:016> dt _RTL_CRITICAL_SECTION_DEBUG 2c8b318
_RTL_CRITICAL_SECTION_DEBUG
+0x000 Type : 0
+0x002 CreatorBackTraceIndex : 0x2911
+0x004 CriticalSection : 0x042c2318 _RTL_CRITICAL_SECTION
+0x008 ProcessLocksList : _LIST_ENTRY [ 0x2c8b358 - 0x2c8b2e8 ]
+0x010 EntryCount : 1
+0x014 ContentionCount : 1
+0x018 Flags : 0xbaadf00d
+0x01c CreatorBackTraceIndexHigh : 0xf00d
+0x01e SpareWORD : 0xbaad
这怎么可能?即使在另一个线程没有调用LeaveCriticalSection的死锁中,我也希望看到关键部分本身被标记为锁定。是否有人有任何调试建议或可能的修复方法?
最佳答案
原来是在没有相应的EnterCriticalSection的情况下调用LeaveCriticalSection的一个错误。这导致关键部分将LockCount和RecursionCount递减为以下状态(LockCount的默认值为-1,RecursionCount为0):
0:016> dt _RTL_CRITICAL_SECTION 1092318
_RTL_CRITICAL_SECTION
+0x000 DebugInfo : 0x....... _RTL_CRITICAL_SECTION_DEBUG
+0x004 LockCount : -2
+0x008 RecursionCount : -1
+0x00c OwningThread : (null)
+0x010 LockSemaphore : 0x.......
+0x014 SpinCount : 0
当执行后续的EnterCriticalSection时,由于RecursionCount不为零,因此挂起-如果RecursionCount为0,线程只能获取关键部分的所有权。但是,它确实增加了LockCount(将其返回到我最初问题中看到的-1)只是为了混淆事情。
总而言之,如果您看到一个关键部分在LockCount和RecursionCount均为-1时暂停线程,则意味着存在过多的解锁。
至于导致它的代码:
if (SysStringLen(bstrState) > 0)
CHECKHR_CS( m_pStateManager->SetState(bstrState), &m_csStateManagerLock );
以及错误检查宏的定义:
#define CHECKHR_CS(x, cs) \
EnterCriticalSection(cs); \
if( FAILED(hr = (x)) ) { \
LeaveCriticalSection(cs); \
return hr; \
} \
LeaveCriticalSection(cs);
该宏在其内容周围缺少花括号,因此如果不满足if语句,则仅跳过EnterCriticalSection。显然是个问题。
关于c++ - 为什么我的线程被关键部分阻塞而没有任何内容?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8830004/