【发布时间】:2012-01-12 04:09:58
【问题描述】:
我遇到了 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 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,然后是 2 个 LeaveCriticalSection。
-
检查临界区没有被删除。来自DeleteCriticalSection:如果一个临界区在它仍然拥有的情况下被删除,等待被删除临界区所有权的线程的状态是未定义的。
-
@hmjd 可能是正确的 0xbaadf00d mead 执行了解除分配。
-
不幸的是,这似乎不是原因。调用 DeleteCriticalSection 的唯一位置是在将临界区作为成员变量的对象的析构函数中。我添加了登录到析构函数只是为了确保它确认析构函数在此之前没有被意外调用。
标签: c++ multithreading critical-section