2009-11-19 142 views
0

手柄我在我的程序下面的代碼:有沒有什麼辦法,輸入/ LeaveCriticalSection可以留下

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

它工作的時間精99.999%,但偶爾把手好像被甩在後面。現在我已經做了一些明顯的事情,比如確保x沒有改變輸入值之間的值,並確保在「// stuff」裏面沒有任何「return」或「break」,但是我想知道是否可以有東西否則會導致進入/離開對留下手柄。也許是內存不足或溢出操作系統或其他任何計數器。

編輯:我是C++新手,該程序最近才從C轉換而來。它在整個程序中的任何地方都沒有例外。

+0

您是如何確定手柄是否剩下?可能它與CriticalSections根本沒有關係(而是來自'stuff'代碼塊的句柄?) – Nicholaz 2009-11-19 14:38:44

+0

我遵循了這部電影中的指南http://channel9.msdn.com/posts/jeff_dailey/Understanding -handle-leaks-and-how-to-use-htrace-to-find-them /(movie now not working right now)。它在windbg中使用!htrace命令。 – Mick 2009-11-19 14:47:27

+0

電影可以從這裏下載:http://mschnlnine.vo.llnwd.net/d1/ch9/1/2/6/7/5/2/341851_leakyhandles.wmv – Mick 2009-11-19 14:50:57

回答

3

如果您沒有明確刪除關鍵部分,並且在關鍵部分存在爭用,那麼您將泄漏一個句柄。當兩個或更多線程重疊嘗試進入單個關鍵部分時,Windows上某些關鍵部分的實現將分配一個信號量。

這不是泄漏。或者說,如果「泄漏」句柄的數量少於或等於您正在使用的全局關鍵部分的數量,那麼這不是泄漏。

+0

這聽起來非常像答案! (除了我不確定我理解它!)您是否說過,當我擁有並使用一系列關鍵部分時,只有在存在爭用時纔會創建句柄? – Mick 2009-11-19 18:02:49

+0

我很困惑 - 當然我不想刪除關鍵部分。我只想刪除由爭用創建的句柄。我會一遍又一遍地使用關鍵部分。 – Mick 2009-11-19 18:25:44

+0

剛剛在別處證實,你的答案是正確的。沒有錯誤,沒有泄漏。由於競爭的稀少,我剛剛被緩慢而穩定的手柄增長所拋棄。 – Mick 2009-11-19 18:34:04

1

由於您使用的是C++版本,因此出現// stuff部分的異常將跳過LeaveCriticalSection()。查找RAII(「資源獲取 - 初始化」)是防止這種情況發生的工具。下面是這樣的類稍微簡單的例子:

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() 

在一個側面說明:死鎖有時可以給一些印象鎖沒有被正確解鎖。

1

最可能的原因是一個例外。你是否捕捉到這個函數中的異常,以及它們是否叫做Leave?另外請注意,最好使用CSingleLock類來鎖定關鍵部分,而不是像這樣使用原始API。通過使用CSingleLock,您可以對異常進行適當的清理。

2

米克,

有很多事情可能發生。

在執行LeaveCriticalSection調用之前,異常會導致控制流退出塊。爲了避免這個問題,您可以使用資源獲取初始化(RAII)模式,結束基於堆棧的對象內臨界區域的輸入&。

但是,如果沒有更完整的列表,則不可能說您的代碼是否存在其他問題。

乾杯 勒布

+0

這是令人尷尬的,但我不知道什麼是「例外」。順便說一句,我很長一段時間的C程序員,而不是新的C++,是一個例外的C + +概念? – Mick 2009-11-19 13:46:46

+0

@米克:你可以在這裏快速瀏覽:http://www.parashift.com/c++-faq-lite/exceptions.html – Naveen 2009-11-19 13:59:14

+0

或者在這裏:http://www.cplusplus.com/doc/tutorial/exceptions/ – Naveen 2009-11-19 14:00:08

1

上SBI的回答擴大(因爲你說你是新來的C++),異常忽略來自地方的代碼中調用它的其餘部分,直到它到達一個地方例外可以被處理(一個'catch') - 唯一的例外是當異常包裝堆棧中的內存時 - 它調用堆棧變量的析構函數。

爲確保始終調用'離開',請使用以下類:(請原諒缺少格式),並將此類的實例和關鍵代碼放在新堆棧中。這確保始終調用「離開」,無論是在非例外還是異常情況下。

編輯:更新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 
0

難道你沒有失去的拉手,不匹配的輸入/發表而是由忘記打電話DeleteCriticalSection。

+0

我所有的關鍵部分都是全局變量。我在main的開始處對它們進行初始化,從那時起關鍵部分的數量保持不變。我從不刪除它們 - 當我退出程序時,我只是讓操作系統殺死它們。 – Mick 2009-11-19 14:23:32

相關問題