2011-11-23 31 views
5

Tôi biết rằng giá trị không hợp lệ được CreateFile trả về là INVALID_HANDLE_VALUE. Nhưng kể từ khi tôi cũng muốn sử dụng RAII nó rất hấp dẫn để chỉ dính HANDLE trong một shared_ptr (như thế này: shared_ptr<void> handle (CreateFile(args),&CloseHandle)) để đảm bảo rằng tay cầm được đóng lại. Mối quan tâm duy nhất của tôi với cách nhanh chóng và dễ dàng này để thực hiện RAII là nếu CreateFile có thể trả về NULL làm giá trị HANDLE.CreateFile có thể trả về NULL không?

+2

Lưu ý rằng bạn phải cẩn thận khi cố gắng làm điều gì đó như thế này. Xem: http://stackoverflow.com/questions/1562421/making-a-handle-raii-compliant-using-shared-ptr-with-a-custom-deleter – tenfour

+1

Đó là ok để tạo ra một wrapper RAII cho các loại hình tài nguyên . Tuy nhiên không sử dụng 'shared_ptr' trừ khi bạn ** thực sự ** cần nó được chia sẻ. Đó là một overkill rất lớn ('shared_ptr' phân bổ nội bộ bộ nhớ thừa trên heap để đếm tham chiếu), cộng với bạn sẽ không có quyền truy cập thuận tiện, chẳng hạn như truyền trực tiếp tới' HANDLE', vì 'shared_ptr' cố ý ngăn chặn điều này. – valdo

+0

điểm tuyệt vời. unique_ptr có lẽ sẽ là một cách tốt hơn để đi .. ở mức độ nỗ lực này. – Dan

Trả lời

6

NULL không phải là một giá trị xử lý hợp lệ. Bạn có thể phân biệt điều này với thực tế là một số hàm API của Windows trả lại NULL để cho biết lỗi. Vì có một chức năng duy nhất để xử lý các chốt, CloseHandle, nó theo sau rằng NULL không phải là giá trị HANDLE hợp lệ. Do đó, CreateFile không bao giờ có thể trả lại NULL.

Raymond Chen đã viết một cảm trên blog bài viết về chủ đề này: Why are HANDLE return values so inconsistent?.

Bây giờ, tôi không biết gì về shared_ptr<> rất muốn thực hiện không bình luận về việc có hay không ý tưởng của bạn là thích hợp. Tôi chỉ trả lời câu hỏi trực tiếp mà bạn đã hỏi.

+0

Tôi không biết rằng 'NULL' có thể không được trả về ngay cả từ các hàm có giá trị trả về" không hợp lệ "là' INVALID_HANDLE_VALUE'. Bạn có chắc là vậy không? Lập luận của bạn là bởi vì 'CloseHandle' có thể phát hiện khi xử lý không hợp lệ được truyền cho nó, bất kể hàm nào trả về nó (miễn là nó là một nhân xử lý hạt nhân). Nhưng OTOH 'CloseHandle' không ** có ** để thực hiện các giá trị không hợp lệ được truyền cho nó. – valdo

+2

@valdo Đối số của tôi là 'CloseHandle' không biết liệu trình xử lý không hợp lệ đến từ CreateFile hay API khác sử dụng' NULL' làm giá trị trả về của nó. Một đối số đơn giản hơn là nếu 'CreateFile' trả về' NULL', thì một tín hiệu chức năng khác có thể thất bại như thế nào? –

+1

Được rồi, tôi hiểu đối số của bạn và có thể là chính xác. Tuy nhiên * về lý thuyết * điều này không chứng minh bất cứ điều gì. Theo tiêu chuẩn 'CloseHandle' không phải nhận ra rằng bạn đã vượt qua một xử lý không hợp lệ cho nó và chỉ im lặng thất bại mà không làm hại, chẳng hạn như đóng tài nguyên khác (không liên quan). Đó là vấn đề của bạn. Bạn có trách nhiệm kiểm tra giá trị trả về của 'CreateXXXX' và không gọi' CloseHandle' nếu tay cầm không hợp lệ. Tuy nhiên, thực tế nói, tôi tin rằng cả hai 'NULL' và' INVALID_HANDLE_VALUE' được dành riêng như là một giá trị không xử lý. – valdo

1

Khi kiểm tra HANDLE để có hiệu lực theo cách tổng quát, hãy kiểm tra cả NULLINVALID_HANDLE_VALUE.

Nhưng tôi không thấy RAII có liên quan gì đến việc liệu CreateFile có thể trả lại NULL hay không. Bạn sẽ cần phải cung cấp mã tùy chỉnh để kiểm tra tính hợp lệ và deallocating để làm cho HANDLE hoạt động với một con trỏ được chia sẻ, vì vậy bạn kiểm soát các kiểm tra này, không phải là lớp con trỏ được chia sẻ.

Nói cách khác, nó không tạo sự khác biệt cho dù đó là con trỏ dùng chung hay bạn sử dụng số HANDLE bình thường, séc cũng giống nhau và bạn phải cung cấp chúng theo cách này.

+1

Thực sự là khá lành tính khi gọi 'CloseHandle' truyền' NULL' hoặc 'INVALID_HANDLE_VALUE'. Nó sẽ là một lỗi, nhưng không có hại sẽ đến từ này. Tôi thừa nhận rằng tôi sẽ không bao bọc một 'HANDLE' theo cách này. Một lớp học 'RAII' đặt biệt sẽ làm tốt công việc. Tôi chắc chắn rằng nó đã được thực hiện một lần gazillion. +1 –

+0

@ David Heffernan Tôi biết rằng giải pháp hoàn chỉnh hơn là viết lớp quản lý xử lý của riêng bạn. Cho phép xem xét điều này một bước theo hướng đó. – Dan

+0

là lý do tại sao tôi quan tâm nếu CreateFile có thể trả về NULL và những gì đã làm với RAII. Tôi đã lo ngại rằng shared_ptr có thể không gọi destructor tùy chỉnh nếu giá trị là null ..khi nhìn sâu vào mã (ít nhất là để tăng) có vẻ như nó không anyway .. Ngoài ra nếu sử dụng chức năng tạo tùy chỉnh mà trả lại một shared_ptr phân biệt giữa một shared_ptr có chứa không có gì vs một có chứa một tay cầm null sẽ là phiền hà – Dan

0

CreateFile không bao giờ trả NULL. Tôi khuyên bạn nên sử dụng trình bao bọc đã tạo ATL::CAtlFile và không tạo một trình bao bọc mới dựa trên shared_ptr.

+0

đó là tất cả tốt và tốt, nhưng cho phép nói rằng tôi thực sự muốn thêm vào thử nghiệm mã trong destructor tùy chỉnh của tôi trước khi thực sự đóng xử lý. – Dan

+0

@Dan: Vâng, sau đó bạn có thể kế thừa CAtlFile và bạn có kiểm tra mã trong destructor hay không. IMHO shader_ptr cho xử lý trông xấu xí. –

+0

vâng cũng IMHO Atl là xấu xí cho bất cứ điều gì nhưng quản lý COM. – Dan

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