2012-10-01 22 views
7

Tôi đang cố gắng để thêm một số debug kiểm tra cho một mã CRITICAL_SECTION mở khóa, và tôi thử như sau:Tại sao thành viên OwningThread của CRITICAL_SECTION loại HANDLE, khi nó biểu thị ID luồng?

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

Từ gỡ lỗi CRITICAL_SECTIONS (Với VS 2005, chủ yếu là trên WindowsXP) Tôi "biết" rằng giá trị của OwningThread (thành viên của cấu trúc RTL_CRITICAL_SECTION được xác định trong winnt.h) là giá trị của th ID của chủ đề giữ khóa.

Tuy nhiên sợi ID được đại diện bởi DWORD (typedef cho unsigned long) giá trị trong khi biến này có kiểu HANDLE (typedef cho void*) đòi hỏi một reinterpret_cast cho việc sử dụng các HandleToULong Macro từ basetsd.h cho đoạn mã trên để làm việc.

Ngay cả những MSDN docs nhà nước:

Khi thread đầu tiên gọi là thói quen EnterCriticalSection, (...) OwningThread trở thành thread ID của người gọi.

Vậy tại sao điều này được xác định là HANDLE?


Chỉnh sửa Lưu ý: Tôi tìm thấy a statement nơi một poster cho thấy HANDLE/DWORD-Id không phù hợp là một số misfeature nổi tiếng của một số internals Windows. Vì vậy, có lẽ đây là trường hợp ở đây quá:

GetCurrentThreadId trả về một DWORD, mà tôi gửi đến các hạt nhân trong một tin nhắn . PsLookupThreadByThreadId lấy Id chủ đề trong HANDLE, ... ...

Đây là lỗi Windows API đã biết ("đã biết" trong đó tôi đã nói chuyện với trình quản lý bộ lọc liên quan DEV về điều này, vì nó hiển thị trong Lọc Quản lý cũng vì vấn đề API Trình quản lý I/O.) Miễn là bạn không có nhiều hơn một nửa tỷ đề và quy trình (chúng sử dụng một bảng xử lý chung), bạn sẽ ổn . Có lẽ vào thời điểm đó là một vấn đề thực sự, chúng tôi sẽ chạy một cái gì đó khác nhau. [RE: ThreadId để xử lý cho 64 bit?, 08 Aug 08 14:21, Tony Mason]

+1

Trong mọi trường hợp, reinterpret_cast là quá mức cần thiết. Một static_cast sẽ làm. Cả HANDLE và DWORD đều là các loại không thể thiếu. –

+0

@ArmenTsirunyan - NO, trong VS2005 bạn không thể sử dụng static_cast để truyền TAY cho một DWORD: 'lỗi C2440: 'static_cast': không thể chuyển đổi từ 'HANDLE' thành 'DWORD'' –

+0

Thật kỳ lạ. Bạn có thể vui lòng cho tôi biết những gì họ đang gõ cho? –

Trả lời

8

Bất kỳ nhận dạng trong SDK có tên bắt đầu với RTL hoặc RTL là mã hoặc tờ khai là một phần của thời gian chạy lớp, keo kết hợp với Winapi được ghi chép đầy đủ với api hệ điều hành gốc không có giấy tờ. Các winapi được đúc bằng đá, hệ điều hành bản địa thay đổi rất nhiều với mỗi bản phát hành Windows. Chắc chắn, keo cũng thay đổi.

Winapi là lớp được tài liệu, hệ điều hành gốc không có giấy tờ. Lớp thời gian chạy là không có giấy tờ là tốt, nhưng theo thời gian các phần của nó đã được tiết lộ. Hoặc là vì nó điền lại một tính năng còn thiếu trong winapi. Hoặc, trong trường hợp này, bởi vì thực sự hữu ích để khắc phục sự cố. Tuy nhiên, một vấn đề cốt lõi khi làm như vậy là một khi một tuyên bố được tiết lộ, Microsoft không bao giờ có thể thay đổi nó nữa. Bởi vì làm như vậy sẽ phá vỡ các chương trình hiện có, một gánh nặng lớn cho khách hàng của mình.

Vì vậy, chắc chắn trường ThreadOwner đã thực sự nắm giữ tay cầm cho chuỗi trong phiên bản Windows trước đó. Lưu ý cách LockSemaphore cũng gây hiểu lầm, nó thực sự là sự kiện tự động đặt lại. Quá muộn để sửa nó, con mèo đã ra khỏi túi.

4

Tôi tin rằng lý do chính là chi tiết triển khai. Tôi sẽ không ngạc nhiên nếu có một thời gian trong lịch sử nó thực sự là một xử lý hoặc một cái gì đó như thế.

Ngoài ra, tôi đặc biệt khuyên bạn không nên sử dụng các thành viên nội bộ trong mã sản xuất và I am not alone. Nếu bạn nhìn kỹ, API đồng bộ sử dụng CRITICAL_SECTION mà bạn sẽ không tìm thấy tài liệu như một cấu trúc trong MSDN, và không RTL_CRITICAL_SECTION (được typedef'ed để CRITICAL_SECTION)

Giá trị được lưu trữ trong OwningThread thành viên được lấy từ CLIENT_ID một phần của Thread Information Block.Trong CLIENT_ID nó như mô hình hóa như PVOID đó là khả năng lý do tại sao nó được mô phỏng theo cách tương tự trong CRITICAL_SECTION:

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

Tôi đã cung cấp một liên kết MSDN đi qua cấu trúc này (được cấp trong phần * Tác vụ gỡ lỗi nâng cao *) vì vậy tôi nghĩ khá OK khi sử dụng * trong mã kiểm tra lỗi *. –

+0

Nó sẽ vẫn không xây dựng nếu cấu trúc thay đổi và tôi cũng không xem xét mã ASSERT mã sản xuất thực, vì nó không được triển khai cho người dùng cuối (tức là trong bản phát hành bản phát hành) –

Các vấn đề liên quan