2012-10-01 16 views
7

我想添加一些調試檢查一個CRITICAL_SECTION解鎖代碼,我試過如下:爲什麼類型HANDLE的CRITICAL_SECTION的OwningThread構件中,當表示該線程ID?

... 
    if (m_pCritSect) { 
    ASSERT(m_pCritSect->OwningThread == GetCurrentThreadId()); 
    LeaveCriticalSection(m_pCritSect); 
    } 
} 

從調試CRITICAL_SECTIONS(在VS 2005,主要是WindowsXP的)我「知道」的價值OwningThread(在winnt.h定義的RTL_CRITICAL_SECTION結構的成員)是個線程的ID持有鎖的值。

然而線程ID由DWORD(的typedef unsigned long)表示的值,而該變量具有類型HANDLE(的typedef void*)規定 一個 reinterpret_cast使用HandleToULong宏從basetsd.h用於上述代碼工作。

即使MSDN docs狀態:

當第一個線程調用EnterCriticalSection的程序,(...) OwningThread成爲主叫方的線程ID。

那麼爲什麼地球上這是定義爲HANDLE


編輯注:我發現a statement其中一張海報表明,手柄/ DWORD-ID不匹配是一些Windows內部的一些已知的不良特性。所以,也許是這樣的話在這裏太:

GetCurrentThreadId返回一個DWORD,這是我在 消息發送到內核。 PsLookupThreadByThreadId採用線程ID在一個HANDLE,... ...

這是一個已知的Windows API的bug(「已知」在我跟 相關過濾經理DEV這一點,因爲它顯示了過濾 經理以及因爲I/O管理器API的問題。)只要你 沒有超過半十億左右的線程和進程(他們 使用一個單一的共享句柄表),你會被罰款。也許到時候 這是一個真正的問題,我們將運行一些不同的東西。 [RE:線程ID來處理64位的? 08年8月8日14:21,託尼梅森]

+1

無論如何reinterpret_cast是矯枉過正。 static_cast會做。 HANDLE和DWORD都是完整的類型。 –

+0

@ArmenTsirunyan - 不,在VS2005中,你不能使用static_cast將句柄轉換爲DWORD:'錯誤C2440:'static_cast':無法從'HANDLE'轉換爲'DWORD'' –

+0

這很奇怪。你能告訴我他們的typedefs是什麼嗎? –

回答

8

在其名稱的SDK任何標識符與RTL開始或RTL是代碼或在運行時的一部分的聲明層,這種粘合劑將有文檔記錄的Winapi與無證原生操作系統api結合在一起。 winapi已經投入使用,每個Windows版本的本地操作系統都會發生巨大變化。膠水也不可避免地發生變化。

winapi是記錄層,本地操作系統沒有記錄。運行時層也沒有記錄,但是隨着時間的推移,它的一部分被揭示了。要麼是因爲它在winapi中填充了缺失的功能。或者,在這種情況下,因爲對於解決問題真的很有用。然而,這樣做的一個核心問題是,一旦聲明被揭示出來,微軟再也無法改變它。因爲這樣做會破壞現有的程序,給客戶帶來很大的負擔。

所以當然,ThreadOwner字段曾經真正地保留了以前Windows版本中線程的句柄。注意LockSemaphore是如何誤導的,它實際上是一個自動重置事件。爲解決這個問題,貓已經不在袋子裏了。

4

我認爲,主要原因是它是一個實施細節。如果在歷史上曾經是真正的句柄或類似的東西,我不會感到驚訝。

此外,我強烈建議不要在生產中使用的代碼,並I am not alone內部成員。如果你仔細觀察,同步API使用CRITICAL_SECTION,你不會找到記錄在MSDN的結構,而不是RTL_CRITICAL_SECTION(這是Typedef的以CRITICAL_SECTION)

存儲在OwningThread成員的值從CLIENT_ID取部分Thread Information Block。在CLIENT_ID它建模爲PVOID爲什麼它被以同樣的方式CRITICAL_SECTION內仿照這很可能是:

typedef struct _CLIENT_ID 
{ 
    PVOID UniqueProcess; 
    PVOID UniqueThread; 
} CLIENT_ID, *PCLIENT_ID; 
+0

我提供了一個MSDN鏈接,該鏈接遍及此結構(授予它在*高級調試任務*部分中),因此我認爲在調試檢查代碼*中使用此*非常合適。 –

+0

如果結構發生變化,它仍然不會生成,並且我也不會考慮ASSERT代碼真正的生產代碼,因爲它沒有部署到最終用戶(即在發佈版本中) –

相關問題