是否有任何方式Enter / LeaveCriticalSection可以留下一个句柄

时间:2009-11-19 13:32:13

标签: c++ multithreading windows-xp

我的程序中有以下代码:

  EnterCriticalSection(&critsec[x]);
  // stuff
  LeaveCriticalSection(&critsec[x]);

99.999%的时间可以正常工作,但偶尔会出现一个手柄。现在我做了一些显而易见的事情,比如确保x没有改变输入之间的值,并确保“// stuff”中没有任何“return”或“break”但是我想知道是否有某些东西否则会导致进入/离开对后面留下一个手柄。可能是内存耗尽或操作系统中的某些计数器耗尽等等。

编辑:我是C ++的新手,该程序最近才从C转换过来。整个程序中没有任何例外。

6 个答案:

答案 0 :(得分:3)

如果您没有明确删除关键部分,并且在关键部分存在争用,则会泄漏句柄。当两个或多个线程在尝试进入单个关键部分时重叠时,Windows上的一些关键部分实现会分配一个信号量。

这不是泄漏。或者更确切地说,如果“泄露”句柄的数量小于或等于您正在使用的全局关键部分的数量,则不会泄漏。

答案 1 :(得分:2)

米克,

有很多事情可能会发生。

异常会导致控制流在执行LeaveCriticalSection调用之前退出块。为了避免这个问题,你可以完成输入和输入。使用资源获取初始化(RAII)模式退出基于堆栈的对象内的关键部分。

但是,如果没有更完整的列表,则无法确定代码是否存在任何其他问题。

干杯 SEB

答案 2 :(得分:1)

由于您处于C ++版本,因此// stuff部分的异常将跳过LeaveCriticalSection()。查找RAII(“Resource-Aquisition-Is-Initialization”)作为防止这种情况发生的工具。这是一个类似于一个简单的例子:

class CriticalSectionLock {
public:
  CriticalSectionLock(CRITICAL_SECTION& c) : cs_(c){EnterCriticalSection(&cs_);}
  ~CriticalSectionLock()                           {LeaveCriticalSection(&cs_);}
private:
  CRITICAL_SECTION& cs_;
};


void f()
{
  CriticalSectionLock lock(critsec[x])
   // stuff
} // lock's destructor will automagically call LeaveCriticalSection()

侧面说明:死锁有时会给人一种锁定未正确解锁的印象。

答案 3 :(得分:1)

最可能的原因是例外。你是否在这个函数中捕获异常以及它们是否调用Leave?另外,请注意,最好使用CSingleLock类来锁定关键部分,而不是使用像这样的原始API。通过使用CSingleLock,您可以保证适当的清理,例外情况。

答案 4 :(得分:1)

扩展sbi的答案(正如你所说的你是C ++的新手),一个例外忽略了调用它的地方的其余代码,直到它到达可以处理异常的地方('catch' ) - 唯一的例外是当异常包装堆栈中的内存时 - 它调用堆栈变量的析构函数。

要确保始终调用“Leave”,请使用以下类:(请原谅缺少格式化),并将此类的实例和关键代码放在新堆栈中。这可以确保在非异常和异常情况下始终调用“Leave”。

编辑:更新p-o-c代码以反映评论。

class AutoCritical
{
public:
  AutoCritical(CritSec * p_CritSec) : m_Sec(p_CritSec) 
   { EnterCriticalSection(m_CritSec); };
  ~AutoCritical() { LeaveCriticalSection(m_CritSec); };
private:
  CritSec * m_Sec;
}; 

呼叫地点:

// non-critical code ....
{   //open stack for critical code
    AutoCritical a(&critsec[x]);
    // do critical stuff here ...
}   // close stack

答案 5 :(得分:0)

您是否可能因为不匹配的Enter / Leave而丢失句柄,而是忘记调用DeleteCriticalSection。