2011-11-23 13 views
5

मुझे पता है कि CreateFile द्वारा दिया गया अमान्य मान INVALID_HANDLE_VALUE है। लेकिन चूंकि मैं भी आरएआईआई का उपयोग करना पसंद करता हूं, इसलिए यह एक साझा_प्टर (जैसे: shared_ptr<void> handle (CreateFile(args),&CloseHandle)) में हैंडल बंद होने के लिए हैंडल को छूने के लिए बहुत मोहक है। आरएआईआई करने के लिए इस त्वरित और आसान तरीके से मेरी एकमात्र चिंता यह है कि यदि CreateFile हैंडल मान के रूप में NULL को वापस कर सकता है।क्या निर्माण कभी भी वापस लौटा सकता है?

+2

ध्यान दें कि आपको ऐसा कुछ करने का प्रयास करते समय सावधान रहना होगा। देखें: http://stackoverflow.com/questions/1562421/making-a-handle-raii-compliant-using-shared-ptr-with-a- कस्टम-deleter – tenfour

+1

इस तरह के संसाधन के लिए आरएआईआई रैपर बनाना ठीक है । हालांकि 'shared_ptr' का उपयोग न करें जबतक कि आपको ** वास्तव में ** साझा करने की आवश्यकता न हो। यह एक विशाल ओवरकिल है ('shared_ptr' आंतरिक रूप से संदर्भ गणना के लिए ढेर पर एक अतिरिक्त मेमोरी आवंटित करता है), साथ ही आपके पास सुविधाजनक पहुंच नहीं होगी, जैसे कि 'हैंडल' पर सीधी कास्टिंग, क्योंकि' shared_ptr' जानबूझकर इसे रोकता है। – valdo

+0

उत्कृष्ट अंक। unique_ptr शायद इस स्तर पर प्रयास करने के लिए एक बेहतर तरीका होगा। – Dan

उत्तर

6

NULL मान्य संभाल मान नहीं है। आप इस तथ्य से यह समझ सकते हैं कि विफलता इंगित करने के लिए कुछ विंडोज एपीआई फ़ंक्शन NULL लौटाते हैं। चूंकि हैंडल का निपटान करने के लिए एक ही फ़ंक्शन है, CloseHandle, यह NULL मान्य है HANDLE मान मान्य नहीं है। इसलिए CreateFile कभी भी NULL वापस नहीं लौटा सकता है।

रेमंड चेन ने इस विषय पर छूने वाले ब्लॉग लेख को लिखा: Why are HANDLE return values so inconsistent?

अब, मुझे shared_ptr<> के बारे में कुछ भी पता नहीं है, इसलिए इस बारे में कोई टिप्पणी नहीं करना चाहिये कि आपका विचार उचित है या नहीं। मैं केवल आपके द्वारा पूछे गए सीधे प्रश्न का उत्तर दे रहा हूं।

+0

मुझे पता नहीं था कि 'NULL' उन कार्यों से भी वापस नहीं किया जा सकता है जिनके लिए "अमान्य" वापसी मान 'INVALID_HANDLE_VALUE' है। क्या आपको यकीन है कि ऐसा है? आपका तर्क यह है कि इस तरह के 'क्लोजहैंडल' द्वारा पता लगाया जा सकता है कि जब अवैध हैंडल पास हो जाता है, इससे कोई फर्क नहीं पड़ता कि कौन सा फ़ंक्शन इसे वापस कर देता है (जब तक यह कर्नेल हैंडल हो)। लेकिन OTOH 'CloseHandle' ** ** पास ** के पास अवैध अमान्य मानों को ले जाने के लिए ** नहीं है। – valdo

+2

@ valdo मेरा तर्क यह है कि 'CloseHandle' यह नहीं जानता कि अमान्य हैंडल CreateFile या अन्य API से आया है जो' NULL' का उपयोग इसके वापसी मान के रूप में करता है। एक और आसान तर्क यह था कि यदि 'CreateFile'' NULL' लौटा, तो दूसरा फ़ंक्शन सिग्नल विफलता कैसे हो सकता है? –

+1

ठीक है, मैं आपके तर्क को समझ गया, और यह शायद सही है। हालांकि * सैद्धांतिक रूप से * यह कुछ भी साबित नहीं करता है। मानक 'क्लोजहैंडल' के मुताबिक यह समझने की ज़रूरत नहीं है कि आपने इसे एक अवैध संभाल पास कर दिया है और किसी भी नुकसान के बिना चुपचाप असफल हो जाता है, जैसे कि किसी अन्य (असंबंधित) संसाधन को बंद करना। यह तुम्हारी समस्या है। 'CreateXXXX' के वापसी मूल्य की जांच करना और हैंडल अमान्य होने पर' CloseHandle' को कॉल न करना आपकी ज़िम्मेदारी है। हालांकि, व्यावहारिक रूप से बोलते हुए, मेरा मानना ​​है कि 'नूल' और 'INVALID_HANDLE_VALUE' दोनों गैर-हैंडल मान के रूप में आरक्षित हैं। – valdo

1

एक सामान्य तरीके से वैधता के लिए हैंडल का परीक्षण करते समय, NULL और INVALID_HANDLE_VALUE दोनों की जांच करें।

लेकिन मुझे नहीं लगता कि आरएआईआई के पास CreateFileNULL वापस कर सकता है या नहीं। HANDLE साझा पॉइंटर के साथ काम करने के लिए आपको वैधता परीक्षण और अस्वीकार करने के लिए कस्टम कोड प्रदान करने की आवश्यकता होगी, इसलिए आप इन चेक के नियंत्रण में हैं, साझा पॉइंटर क्लास नहीं।

दूसरे शब्दों में, यह कोई फर्क नहीं पड़ता कि यह किसी साझा सूचक में है या आप सामान्य HANDLE का उपयोग करते हैं, तो चेक बिल्कुल वही हैं, और आपको उन्हें किसी भी तरह से प्रदान करना होगा।

+1

यह वास्तव में 'क्लोजहैंडल' को 'न्यूल' या 'INVALID_HANDLE_VALUE' से गुजरने के लिए सौम्य है। यह एक त्रुटि होगी, लेकिन इससे कोई नुकसान नहीं होगा। मैं मानता हूं कि मैं इस तरह से 'हैंडल' लपेटूंगा। एक bespoke 'RAII' वर्ग नौकरी अच्छी तरह से किया जाएगा। मुझे यकीन है कि एक गजियन बार किया गया है। +1 –

+0

@ डेविड हेफरनान मैं अच्छी तरह से जानता हूं कि अधिक संपूर्ण समाधान आपके स्वयं के हैंडल प्रबंधन वर्ग को लिखना होगा। चलिए इस दिशा में एक कदम मानते हैं। – Dan

+0

क्यों मुझे परवाह है कि CreateFile NULL वापस कर सकता है और उसे RAII के साथ क्या करना है। मुझे चिंतित था कि यदि शेयर शून्य था तो share_ptr कस्टम विनाशक को कॉल नहीं कर सकता है ..कोड पर गहराई से देखने पर (कम से कम बढ़ावा देने के लिए) ऐसा लगता है कि यह वैसे भी करता है .. अगर कस्टम सृजन फ़ंक्शंस का उपयोग करना जो एक shared_ptr को साझा_ptr के बीच अंतर करता है जिसमें कुछ भी नहीं है जिसमें शून्य संभाल होता है तो परेशानी होगी – Dan

0

CreateFile कभी भी NULL देता है। मेरा सुझाव है कि आप पहले से ही बनाए गए रैपर ATL::CAtlFile का उपयोग करें और shared_ptr पर आधारित एक नया न करें।

+0

अच्छा और अच्छा है, लेकिन मान लें कि मैं वास्तव में हैंडल बंद करने से पहले अपने कस्टम विनाशक में परीक्षण कोड में जोड़ना चाहता था। – Dan

+0

@Dan: ठीक है, तो आप CAtlFile का उत्तराधिकारी हो सकते हैं और आप विनाशक में कोड का परीक्षण कर सकते हैं। हैंडल के लिए IMHO shader_ptr बदसूरत लग रहा है। –

+0

हाँ अच्छी तरह से IMHO अटलांट COM के प्रबंधन के अलावा कुछ भी बदसूरत है। – Dan

संबंधित मुद्दे