7

CRITICAL_SECTION ロック解除コードのデバッグ チェックを追加しようとしていますが、次のことを試しました。

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

CRITICAL_SECTIONS のデバッグから (VS 2005 では、ほとんどが WindowsXP 上で) (で定義されOwningThreadた構造体のメンバー) の値が、ロックを保持しているスレッドのIDの値であることを「知っています」 。RTL_CRITICAL_SECTIONwinnt.h

DWORDただし、スレッド ID は(typedef for ) 値で表されunsigned longますが、この変数には型HANDLE(typedef for void*) があり、上記のコードが機能するにはマクロを使用する必要があります。reinterpret_castHandleToULongbasetsd.h

MSDNのドキュメントにも次のように記載されています。

最初のスレッドが EnterCriticalSection ルーチンを呼び出すと、(...) OwningThread が呼び出し元のスレッド ID になります。

では、なぜこれが として定義されているのHANDLEでしょうか。


編集注: HANDLE / DWORD-Id の不一致は、一部の Windows 内部の既知の不具合であるとポスターが示唆しているステートメントを見つけました。だから多分これはここでも当てはまります:

GetCurrentThreadId は DWORD を返します。これをメッセージでカーネルに送信します。PsLookupThreadByThreadId は HANDLE でスレッド ID を受け取ります... ...

これは Windows API の既知のバグです (I/O Manager API の問題により、フィルター マネージャーにも表示されるため、関連するフィルター マネージャーの DEV にこの問題について話したという点で "既知" です)。 5 億以上のスレッドとプロセス (それらは 1 つの共有ハンドル テーブルを使用します) を持っている場合は問題ありません。たぶん、それが本当の問題になるまでに、私たちは何か違うことを実行するでしょう. [ RE: 64 ビットの HANDLE への ThreadId ? 、08 年 8 月 8 日 14:21、トニー メイソン]

4

2 に答える 2

8

名前がRTLまたはRtlで始まるSDKの識別子は、ランタイムレイヤーの一部であるコードまたは宣言であり、十分に文書化されたWinapiと文書化されていないネイティブオペレーティングシステムAPIを結合します。winapiは石に鋳造されており、ネイティブオペレーティングシステムはWindowsのリリースごとに大きく変化します。必然的に、接着剤も変化します。

winapiは文書化されたレイヤーであり、ネイティブオペレーティングシステムは文書化されていません。ランタイムレイヤーも文書化されていませんでしたが、時間の経過とともにその一部が明らかになりました。これは、winapiで欠落している機能を埋め戻すためです。または、この場合、問題のトラブルシューティングに本当に役立つためです。ただし、そうすることの1つの主要な問題は、宣言が明らかになると、Microsoftがそれを二度と変更できないことです。そうすることは既存のプログラムを壊すので、その顧客に大きな負担をかけます。

したがって、確かに、ThreadOwnerフィールドは、以前のWindowsバージョンでスレッドへのハンドルを実際に保持していました。LockSemaphoreも誤解を招く可能性があることに注意してください。これは、実際には自動リセットイベントです。それを修正するには遅すぎます、猫は袋から出ています。

于 2012-10-01T16:19:49.873 に答える
4

主な理由は、実装の詳細であると思います。歴史の中で、それが本当にハンドルかそのようなものであったとしても、私は驚かないでしょう。

さらに、本番コードで内部メンバーを使用しないことを強くお勧めします。私だけではありません。よく見ると、同期APIはCRITICAL_SECTION、MSDNで構造として文書化されていないものを使用しており、RTL_CRITICAL_SECTION(CRITICAL_SECTIONにtypedefされている)ではありません。

メンバーに格納される値は、スレッド情報ブロックOwningThreadのCLIENT_ID部分から取得されます。CLIENT_IDでは、PVOIDとしてモデル化されているため、CRITICAL_SECTION内で同じ方法でモデル化されている可能性があります。

typedef struct _CLIENT_ID
{
   PVOID UniqueProcess;
   PVOID UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
于 2012-10-01T14:49:55.877 に答える