我在 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 命令没有指示任何内容,转储临界区表明它没有被锁定,如以下结构中的 null 所有者和 -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/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返