क्या रिलीज बिल्ड में जोर होना चाहिए


21

assertC ++ में डिफ़ॉल्ट व्यवहार रिलीज बिल्ड में कुछ नहीं करना है। मुझे लगता है कि यह प्रदर्शन कारणों से किया जाता है और शायद उपयोगकर्ताओं को बुरा त्रुटि संदेश देखने से रोकने के लिए किया जाता है।

हालाँकि, मैं यह तर्क दूंगा कि उन स्थितियों को, जहाँ से assertनिकाल दिया गया था, लेकिन अक्षम कर दिया गया था और भी अधिक तकलीफदेह है क्योंकि आवेदन तब शायद लाइन के नीचे और भी बुरे तरीके से दुर्घटनाग्रस्त हो जाएगा क्योंकि कुछ आक्रमणकारी टूट गए थे।

इसके अतिरिक्त, मेरे लिए प्रदर्शन तर्क केवल तभी मायने रखता है जब यह एक औसत दर्जे की समस्या हो। assertमेरे कोड में अधिकांश एस अधिक जटिल नहीं हैं

assert(ptr != nullptr);

जिसका अधिकांश कोड पर छोटा प्रभाव पड़ेगा।

यह मुझे इस प्रश्न की ओर ले जाता है: क्या रिलीज बिल्ड में अभिकथन (मतलब अवधारणा, विशिष्ट कार्यान्वयन नहीं) सक्रिय होना चाहिए? क्यों नहीं)?

कृपया ध्यान दें कि यह प्रश्न यह नहीं है कि रिलीज़ बिल्ड (जैसे #undef _NDEBUGसेल्फ असेस् टर्ड इम्प्लीमेंटेशन) का उपयोग कैसे किया जाए। इसके अलावा, यह तीसरे पक्ष / मानक पुस्तकालय कोड में लेकिन मेरे द्वारा नियंत्रित कोड में जोर देने के बारे में नहीं है।


मैं स्वास्थ्य देखभाल बाजार में एक वैश्विक खिलाड़ी को जानता हूं जिन्होंने ग्राहक साइटों पर अपने अस्पताल सूचना प्रणाली का डिबग संस्करण स्थापित किया है। उन्होंने माइक्रोसॉफ्ट के साथ C ++ डिबग लाइब्रेरी को स्थापित करने के लिए एक विशेष समझौता किया था। ठीक है, उनके उत्पाद की गुणवत्ता थी ...
बर्नहार्ड हिलर

3
एक पुरानी कहावत है कि "थकावटों को दूर करना थोड़ा सा है, जैसे कि बंदरगाह में अभ्यास करने के लिए लाइफ-जैकेट पहनना, लेकिन तब जीवन-जैकेट को पीछे छोड़ देना जब आपका जहाज खुले समुद्र में चला जाता है" ( wiki.c2.com/?AssertionsAsDeensiveProgramming ) । मैं व्यक्तिगत रूप से उन्हें डिफ़ॉल्ट रूप से रिलीज़ बिल्ड में सक्षम रखता हूं। दुर्भाग्य से, इस अभ्यास सी ++ दुनिया में बहुत आम नहीं है, लेकिन कम से कम प्रसिद्ध सेल्सियस पर ++ अनुभवी जेम्स Kanze हमेशा रिलीज में दावे रखने के पक्ष में तर्क करने के लिए इस्तेमाल बनाता है: stackoverflow.com/a/12162195/3313064
क्रिश्चियन हैकल

जवाबों:


20

क्लासिक assertपुराने मानक C लाइब्रेरी से एक उपकरण है, C ++ से नहीं। यह अभी भी C ++ में उपलब्ध है, कम से कम पश्चगामी संगतता के कारणों के लिए।

मेरे पास हाथ में सी मानक कामों की कोई सटीक समयरेखा नहीं है, लेकिन मुझे पूरा यकीन है कि assertK & R C उस समय के बाद (1978 के आसपास) आया था, जिसके तुरंत बाद उपलब्ध था। क्लासिक सी में, मजबूत प्रोग्राम लिखने के लिए, NULL पॉइंटर टेस्ट और सरणी सीमा जाँच को जोड़कर C ++ की तुलना में अधिक बार किया जाना चाहिए। NULL पॉइंटर टेस्ट के सकल को पॉइंटर्स के बजाय संदर्भ और / या स्मार्ट पॉइंटर्स का उपयोग करके टाला जा सकता है, और उपयोग करके std::vector, सरणी सीमा की जाँच अक्सर अनावश्यक होती है। इसके अलावा, 1980 में हिट प्रदर्शन निश्चित रूप से आज की तुलना में बहुत अधिक महत्वपूर्ण था। इसलिए मुझे लगता है कि इस बात की बहुत अधिक संभावना है कि "अभिकर्ता" को केवल डिबग बिल्ड में डिफ़ॉल्ट रूप से सक्रिय करने के लिए डिज़ाइन किया गया था।

इसके अलावा, उत्पादन कोड में वास्तविक त्रुटि से निपटने के लिए, एक फ़ंक्शन जो केवल कुछ स्थिति या अपरिवर्तनीयता का परीक्षण करता है, और प्रोग्राम को क्रैश करता है यदि स्थिति पूरी नहीं होती है, तो अधिकांश मामलों में पर्याप्त लचीला नहीं होता है। डिबगिंग के लिए, जो शायद ठीक है, क्योंकि जो प्रोग्राम चलाता है और त्रुटि का अवलोकन करता है, उसके लिए आमतौर पर डिबगर होता है जो विश्लेषण करता है कि क्या होता है। उत्पादन कोड के लिए, हालांकि, एक समझदार समाधान के लिए एक फ़ंक्शन या तंत्र होना चाहिए

  • कुछ स्थिति का परीक्षण करता है (और उस स्कोप पर निष्पादन रोक देता है जहाँ स्थिति विफल हो जाती है)

  • स्थिति स्पष्ट न होने की स्थिति में एक स्पष्ट त्रुटि संदेश प्रदान करता है

  • त्रुटि संदेश लेने के लिए बाहरी क्षेत्र की अनुमति देता है और इसे एक विशिष्ट संचार चैनल पर आउटपुट करता है। यह चैनल कुछ ऐसा हो सकता है जैसे stderr, एक मानक लॉग फ़ाइल, GUI प्रोग्राम में एक संदेश बॉक्स, कॉलबैक से निपटने वाली सामान्य त्रुटि, नेटवर्क-सक्षम त्रुटि चैनल, या जो भी सॉफ़्टवेयर के विशेष टुकड़े के लिए सबसे उपयुक्त हो।

  • प्रति-केस बेस पर बाहरी स्कोप को यह तय करने की अनुमति देता है कि क्या कार्यक्रम को शान से समाप्त होना चाहिए, या यदि इसे जारी रखना चाहिए।

(बेशक, ऐसी परिस्थितियां भी हैं जहां एक अधूरी हालत के मामले में कार्यक्रम को तुरंत समाप्त करना एकमात्र समझदार विकल्प है, लेकिन ऐसे मामलों में, यह रिलीज बिल्ड में भी होना चाहिए, न कि केवल डिबग बिल्ड में)।

चूंकि क्लासिक assertयह सुविधाएँ प्रदान नहीं करता है, इसलिए यह रिलीज़ बिल्ड के लिए एक अच्छा फिट नहीं है, यह मानते हुए कि रिलीज़ बिल्ड उत्पादन में एक है।

अब आप पूछ सकते हैं कि सी स्टैंडर्ड लिब में ऐसा कोई फंक्शन या मैकेनिज्म क्यों नहीं है जो इस तरह का लचीलापन प्रदान करता है। दरअसल, सी ++ में, एक मानक तंत्र है जिसमें ये सभी विशेषताएं (और अधिक) हैं, और आप इसे जानते हैं: इसे अपवाद कहा जाता है

C में, हालांकि, प्रोग्रामिंग भाषा के भाग के रूप में अपवादों की कमी के कारण सभी उल्लेखित विशेषताओं के साथ त्रुटि से निपटने के लिए एक अच्छा, सामान्य उद्देश्य मानक तंत्र लागू करना कठिन है। इसलिए अधिकांश सी कार्यक्रमों में रिटर्न कोड, या "गोटो", या "लॉन्ग जंप", या उस के मिश्रण के साथ अपनी स्वयं की त्रुटि हैंडलिंग तंत्र है। ये अक्सर व्यावहारिक समाधान होते हैं जो विशेष प्रकार के कार्यक्रम में फिट होते हैं, लेकिन सी मानक पुस्तकालय में फिट होने के लिए "सामान्य उद्देश्य पर्याप्त" नहीं हैं।


आह, सी विरासत के बारे में पूरी तरह से भूल गया (इसके सभी के बाद #include <cassert>)। यह पूरी तरह से अब समझ में आता है।
कोई नहीं

1
मैं इस पूरे जवाब से पूरी तरह असहमत हूं। एक अपवाद को फेंकने पर जब आपके आवेदन को पता चला है कि इसका स्रोत कोड छोटी गाड़ी है, जावा जैसी भाषाओं में अंतिम उपाय है जो बेहतर नहीं कर सकता है, लेकिन सी ++ में, इस तरह से ऐसी स्थिति में कार्यक्रम को तुरंत समाप्त कर सकता है। आप नहीं चाहते कि स्टैक अनइंडिंग उस बिंदु पर निष्पादित किए जाने वाले किसी भी अन्य ऑपरेशन का कारण बने । एक छोटी गाड़ी प्रोग्राम संभवतः भ्रष्ट डेटा को फाइल, डेटाबेस या नेटवर्क सॉकेट में लिख सकता है। बस ASAP क्रैश (और संभवतः एक बाहरी तंत्र द्वारा फिर से शुरू की गई प्रक्रिया है)।
क्रिश्चियन हैकल

1
@ChristianHackl: मैं मानता हूं कि ऐसी परिस्थितियां हैं जहां एक कार्यक्रम को समाप्त करना एकमात्र व्यवहार्य विकल्प है, लेकिन फिर यह रिलीज मोड में भी होना चाहिए, और assertइसके लिए गलत उपकरण भी है (अपवाद फेंकना वास्तव में गलत प्रतिक्रिया भी हो सकती है। )। हालांकि, मुझे पूरा यकीन है कि assertसी में बहुत सारे परीक्षणों के लिए भी इस्तेमाल किया गया था जहां सी ++ में आज अपवादों का उपयोग किया जाएगा।
डॉक्टर ब्राउन

15

यदि आप पाते हैं कि आप चाहते हैं कि आपको गलत काम करने के लिए कहा गया था तो एक विज्ञप्ति में सक्षम थे।

मुखरता की बात यह है कि वे एक रिलीज में सक्षम नहीं हैं। यह कोड के साथ विकास के दौरान आक्रमणकारियों के परीक्षण की अनुमति देता है जो अन्यथा मचान कोड होना चाहिए। कोड जिसे रिलीज से पहले हटाना होगा।

यदि आपके पास ऐसा कुछ है जो आपको लगता है कि रिलीज के दौरान भी परीक्षण किया जाना चाहिए, तो कोड लिखें जो इसे परीक्षण करता है। If throwनिर्माण बहुत अच्छी तरह से काम करता है। यदि आप दूसरे थ्रो से अलग कुछ कहना चाहते हैं तो बस एक वर्णनात्मक अपवाद का उपयोग करें जो कहता है कि आप क्या कहना चाहते हैं।

ऐसा नहीं है कि आप यह नहीं बदल सकते हैं कि आप किस तरह से उपयोग करते हैं। यह है कि ऐसा करने से आपको कुछ उपयोगी नहीं मिल रहा है, अपेक्षाओं के अनुरूप चलता है, और आपको कोई रास्ता नहीं छोड़ता है कि क्या करने के लिए अभिप्रेत था। उन परीक्षणों को जोड़ें जो एक रिलीज में निष्क्रिय हैं।

मैं मुखर के विशिष्ट कार्यान्वयन के बारे में बात नहीं कर रहा हूं, लेकिन एक अवधारणा की अवधारणा। मैं मुखर या पाठकों को भ्रमित नहीं करना चाहता। मेरा कहने का मतलब यह था कि यह पहली जगह पर क्यों है। कोई अतिरिक्त रिलीज़_स्सर्ट क्यों नहीं है? क्या इसकी कोई आवश्यकता नहीं है? रिलीज में अक्षम होने के पीछे तर्क क्या है? - कोई नहीं

कोई relase_assert क्यों? सच कहूँ तो क्योंकि उत्पादन के लिए मुखर पर्याप्त नहीं हैं। हाँ वहाँ एक की जरूरत है, लेकिन कुछ भी नहीं है कि अच्छी तरह से जरूरत को पूरा करता है। ओह यकीन है कि आप अपने खुद के डिजाइन कर सकते हैं। यंत्रवत् आपके थ्रो फंक्शन को फेंकने के लिए केवल एक बूल और एक अपवाद की आवश्यकता होती है। और यह आपकी आवश्यकताओं के अनुरूप हो सकता है। लेकिन आप वास्तव में डिज़ाइन को सीमित कर रहे हैं। इसलिए यह मुझे आश्चर्यचकित नहीं करता है कि आपकी भाषाओं की लाइब्रेरी में अपवाद फेंकने जैसी प्रणाली में कोई बेक नहीं है। यह निश्चित रूप से ऐसा नहीं है कि आप ऐसा नहीं कर सकते। दूसरों के पास है । लेकिन उस मामले से निपटना जहां चीजें गलत होती हैं, ज्यादातर कार्यक्रमों के लिए 80% काम है। और अभी तक किसी ने हमें नहीं दिखाया है एक अच्छा एक आकार सभी समाधान फिट बैठता है। इन मामलों से प्रभावी ढंग से निपटना जटिल हो सकता है। अगर हम एक डिब्बाबंद रिलीज़_पास सिस्टम रखते थे जो हमारी ज़रूरतों से कम हो जाता था, तो मुझे लगता है कि इससे अच्छा नुकसान होता। आप एक अच्छे अमूर्त के लिए पूछ रहे हैं जिसका मतलब है कि आपको इस समस्या के बारे में सोचना नहीं होगा। मैं भी एक चाहता हूं, लेकिन ऐसा नहीं लगता कि हम अभी तक वहां हैं।

रिलीज में एसेर्स को क्यों अक्षम किया गया है? स्कैफोल्डिंग कोड की उम्र में ऊँचाई पर असेस्मेंट बनाए गए। कोड हमें निकालना पड़ा क्योंकि हमें पता था कि हम इसे उत्पादन में नहीं चाहते थे, लेकिन हमें पता था कि बग को खोजने में मदद करने के लिए हम विकास में दौड़ना चाहते थे। Asserts if (DEBUG)पैटर्न का एक क्लीनर विकल्प था जो हमें कोड छोड़ देता है लेकिन इसे अक्षम कर देता है। इससे पहले कि यूनिट टेस्टिंग कोड को प्रोडक्शन कोड से अलग करने का मुख्य तरीका था। विशेषज्ञ इकाई परीक्षकों द्वारा, यहां तक ​​कि आशाओं को स्पष्ट करने और उन मामलों को कवर करने के लिए, जो अभी भी इकाई परीक्षण की तुलना में बेहतर करते हैं, आज भी उपयोग किया जाता है।

उत्पादन में सिर्फ डिबगिंग कोड क्यों नहीं छोड़ते? क्योंकि उत्पादन कोड को कंपनी को शर्मिंदा करने की जरूरत नहीं है, हार्ड ड्राइव को प्रारूपित नहीं करना है, डेटाबेस को भ्रष्ट नहीं करना है, और राष्ट्रपति को धमकी भरे ईमेल नहीं भेजना है। संक्षेप में यह एक सुरक्षित स्थान पर डिबगिंग कोड लिखने में सक्षम होना अच्छा है जहां आपको इसके बारे में चिंता करने की आवश्यकता नहीं है।


2
मुझे लगता है कि मेरा सवाल है: रिलीज से पहले इस कोड को क्यों हटाया गया है? चेक एक प्रदर्शन नाली के अधिक नहीं हैं और अगर वे विफल होते हैं तो निश्चित रूप से एक समस्या है जो मैं एक अधिक प्रत्यक्ष त्रुटि संदेश के बारे में पसंद करूंगा। एक जोर देने के बजाय एक अपवाद का उपयोग करने से मुझे क्या लाभ होता है? मैं शायद असंबंधित कोड यह करने में सक्षम होना नहीं चाहता catch(...)
कोई नहीं

2
@ कोई नहीं गैर-मुखर आवश्यकताओं के लिए जोर लगाने का उपयोग नहीं करने का सबसे बड़ा लाभ आपके पाठकों को भ्रमित नहीं कर रहा है। यदि आप कोड को अक्षम नहीं करना चाहते हैं, तो मुहावरों का उपयोग न करें जो संकेत देते हैं कि यह होगा। यह उतना ही बुरा है जितना if (DEBUG)कि डिबगिंग कोड के अलावा किसी अन्य चीज़ को नियंत्रित करने के लिए उपयोग करना। सूक्ष्म अनुकूलन का मतलब आपके मामले में कुछ भी नहीं हो सकता है। लेकिन मुहावरे को सिर्फ इसलिए विकृत नहीं किया जाना चाहिए क्योंकि आपको इसकी आवश्यकता नहीं है।
कैंडिड_ऑरेंज

मुझे लगता है कि मैंने अपना इरादा पर्याप्त स्पष्ट नहीं किया। मैं किसी विशिष्ट कार्यान्वयन के बारे में बात नहीं कर रहा हूं assertलेकिन एक अवधारणा की अवधारणा। मैं assertपाठकों का दुरुपयोग या भ्रमित नहीं करना चाहता । मेरा कहने का मतलब यह था कि यह पहली जगह पर क्यों है। कोई अतिरिक्त क्यों नहीं है release_assert? क्या इसकी कोई आवश्यकता नहीं है? रिलीज में अक्षम होने के पीछे तर्क क्या है?
कोई नहीं

2
You're asking for a good abstraction.मैं उसके बारे में निश्चित नहीं हूं। मैं मुख्य रूप से उन मुद्दों से निपटना चाहता हूं जहां कोई वसूली नहीं होती है और ऐसा कभी नहीं होना चाहिए। इसे साथ ले जाएं Because production code needs to [...] not format the hard drive [...]और मैं उन मामलों के लिए कहूंगा, जहां हमलावरों को तोड़ा गया है, मैं कभी भी यूबी पर रिलीज में जोर डालूंगा।
कोई नहीं

1
@ कोई भी "समस्याएँ नहीं हैं जहाँ कोई वसूली नहीं है" अपवादों को फेंकने और उन्हें न पकड़कर निपटा जा सकता है। आप ध्यान दें कि उन्हें अपवाद के संदेश पाठ में कभी नहीं होना चाहिए।
कैंडिड_ऑरेंज

4

दावे एक डिबगिंग उपकरण हैं , न कि रक्षात्मक प्रोग्रामिंग तकनीक। यदि आप सभी परिस्थितियों में सत्यापन करना चाहते हैं, तो एक सशर्त लिखकर सत्यापन करें - या बॉयलरप्लेट को कम करने के लिए अपना स्वयं का मैक्रो बनाएं।


4

assertटिप्पणियों की तरह प्रलेखन का एक रूप है। टिप्पणियों की तरह, आप आम तौर पर उन्हें ग्राहकों को नहीं भेजेंगे - वे रिलीज़ कोड में नहीं हैं।

लेकिन टिप्पणियों के साथ समस्या यह है कि वे पुराने हो सकते हैं, और फिर भी वे अंदर रह गए हैं। यही कारण है कि asserts अच्छे हैं - वे डीबग मोड में जांचे जाते हैं। जब मुखर अप्रचलित हो जाता है, तो आप इसे जल्दी से खोज लेते हैं, और फिर भी पता चल जाएगा कि मुखर को कैसे ठीक किया जाए। वह टिप्पणी जो 3 साल पहले पुरानी हो गई थी? किसी का अनुमान।


1
तो इससे पहले कि कोई चीज खराब हो जाए, एक असफल आक्रमणकारी पर गर्भपात करना कोई वैध उपयोग मामला नहीं है?
कोई नहीं

3

यदि आप नहीं चाहते हैं कि "मुखर" को बंद कर दिया जाए, तो एक सरल फ़ंक्शन लिखने के लिए स्वतंत्र महसूस करें जिसका समान प्रभाव है:

void fail_if(bool b) {if(!b) std::abort();}

यही है, assertपरीक्षण के लिए है जहां आप चाहते हैं कि वे शिप किए गए उत्पाद में चले जाएं। यदि आप चाहते हैं कि परीक्षण कार्यक्रम के परिभाषित व्यवहार का हिस्सा हो, assertतो गलत उपकरण है।


1
मैं इससे अच्छी तरह वाकिफ हूं। यह सवाल अधिक है कि डिफॉल्ट इस तरह से क्यों है?
कोई नहीं

3

यह तर्क देने के लिए व्यर्थ है कि मुखर को क्या करना चाहिए, यह वह करता है जो वह करता है। यदि आप कुछ अलग चाहते हैं, तो अपना स्वयं का फ़ंक्शन लिखें। उदाहरण के लिए, मेरे पास Assert है जो डीबगर में बंद हो जाता है या कुछ भी नहीं करता है, मेरे पास AssertFatal है जो ऐप को क्रैश कर देगा, मेरे पास बूल फ़ंक्शंस हैं Asserted और AssertionFailed जो Assert और परिणाम लौटाता है ताकि मैं दोनों Assert और स्थिति को संभाल सकूं।

किसी भी अप्रत्याशित समस्या के लिए आपको यह तय करने की आवश्यकता है कि डेवलपर और उपयोगकर्ता दोनों के लिए इसे संभालने का सबसे अच्छा तरीका क्या है।


यह दावा करना मेरा उद्देश्य नहीं था कि मुखर क्या करना चाहिए। इस सवाल के लिए मेरी प्रेरणा यह थी कि रिलीज़ बिल्ड में न होने के पीछे तर्क का पता लगाना क्योंकि मैं अपने बारे में लिखने वाला हूं और उपयोग के मामलों, उम्मीदों और जाल के बारे में जानकारी इकट्ठा करना चाहता हूं।
कोई नहीं

हम्म, मुखर verify(cond)करने और परिणाम वापस करने का सामान्य तरीका नहीं होगा ?
डेडुप्लिकेटर

1
मैं रूबी में कोडिंग कर रहा हूं, सी नहीं, लेकिन मैं ऊपर दिए गए अधिकांश जवाबों से असहमत हूं, क्योंकि एक बैकट्रेस को प्रिंट करने के साथ प्रोग्राम को रोकना मेरे लिए एक रक्षात्मक प्रोग्रामिंग तकनीक के रूप में ठीक काम करता है ....... मेरी टिप्पणी फिट नहीं थी पात्रों में अधिकतम टिप्पणी आकार तो मैंने नीचे एक और उत्तर लिखा है।
नकीलोन

2

जैसा कि दूसरों ने बताया, assertप्रोग्रामर गलतियों के खिलाफ रक्षा के अपने अंतिम गढ़ की तरह है जो कभी नहीं होना चाहिए। वे पवित्रता की जाँच कर रहे हैं कि उम्मीद है कि जब तक आप जहाज से सही और बाएँ विफल नहीं होना चाहिए।

यह भी है तैयार किया गया है , बनाता है स्थिर रिलीज से हटाया जा करने के लिए जो कुछ भी कारणों के लिए डेवलपर्स उपयोगी लग सकते: सौंदर्यशास्त्र, प्रदर्शन, जो कुछ भी वे चाहते हैं। यह एक रिलीज बिल्ड से डिबग बिल्ड को अलग करने का एक हिस्सा है, और परिभाषा के अनुसार एक रिलीज बिल्ड इस तरह के सिद्धांतों से रहित है। इसलिए यदि आप अनुरूप "रिलीज बिल्ड बिल्ड थ्रू में जगह" जारी करना चाहते हैं, तो डिजाइन का एक तोड़फोड़ है, जो रिलीज के निर्माण में एक प्रयास होगा_DEBUG प्रीप्रोसेसर परिभाषा के और कोई NDEBUGपरिभाषित नहीं होगा ; यह वास्तव में अब एक रिलीज बिल्ड नहीं है।

डिजाइन मानक पुस्तकालय में भी फैली हुई है। कई लोगों के बीच एक बहुत ही बुनियादी उदाहरण के रूप में, यह सुनिश्चित करने के लिए कि आप सीमा से बाहर वेक्टर की जाँच नहीं कर रहे हैं, एक पवित्रता की जांच के बहुत सारे कार्यान्वयन std::vector::operator[]होंगे assert। और मानक लाइब्रेरी बहुत अच्छा प्रदर्शन करना शुरू कर देगी, यदि आप एक रिलीज बिल्ड में इस तरह के चेक को सक्षम करते हैं तो बहुत बुरा होगा। vectorउपयोग करने का एक मानदंडoperator[]और एक सादे पुराने डायनेमिक ऐरे के खिलाफ शामिल किए गए ऐसे जोर के साथ एक ctor अक्सर डायनामिक ऐरे को दिखाएगा जब तक कि आप इस तरह के चेक को अक्षम न कर दें, इसलिए वे अक्सर तुच्छ तरीकों से बहुत दूर तक प्रभाव प्रदर्शन करते हैं। एक अशक्त सूचक यहाँ जाँच करता है और सीमा जाँच से बाहर वास्तव में एक बड़ा खर्च बन सकता है अगर इस तरह के चेक को महत्वपूर्ण छोरों में हर फ्रेम पर लाखों बार लागू किया जा रहा हो, कोड से पहले के रूप में सरल रूप से एक स्मार्ट पॉइंटर को डीरफेर करना या किसी ऐक्सेस को एक्सेस करना।

तो आप सबसे अधिक संभावना है कि नौकरी के लिए एक अलग उपकरण चाहते हैं और एक जिसे रिलीज से छोड़ा नहीं जाना चाहिए, यदि आप चाहते हैं कि रिलीज बिल्ड प्रमुख क्षेत्रों में इस तरह की पवित्रता की जांच करें। सबसे उपयोगी मुझे व्यक्तिगत रूप से मिल रहा है। उस स्थिति में, जब कोई उपयोगकर्ता बग की रिपोर्ट करता है, तो चीजें बहुत आसान हो जाती हैं यदि वे एक लॉग संलग्न करते हैं और लॉग की अंतिम पंक्ति मुझे एक बड़ा सुराग देती है कि बग कहां हुआ और यह क्या हो सकता है। फिर, डिबग बिल्ड में अपने कदमों को फिर से शुरू करने पर, मैं शायद एक असफलता प्राप्त कर सकता हूं, और यह कि आगे विफलता मुझे अपना समय सुव्यवस्थित करने के लिए बहुत बड़ा सुराग देती है। अभी तक लॉगिंग अपेक्षाकृत महंगी है, इसलिए मैं इसका उपयोग अत्यंत निम्न-स्तर की शुद्धता जांचने के लिए नहीं करता हूं, जैसे यह सुनिश्चित करना कि एक सामान्य डेटा संरचना में कोई सीमा से बाहर नहीं पहुँचा जा सकता है।

फिर भी, और आपके साथ कुछ हद तक, मैं एक उचित मामला देख सकता हूं, जहां आप वास्तव में परीक्षकों को अल्फा परीक्षण के दौरान डिबग बिल्ड से मिलते-जुलते हाथ देना चाह सकते हैं, उदाहरण के लिए, अल्फा परीक्षकों के एक छोटे समूह के साथ, जो कहते हैं, एक एनडीए पर हस्ताक्षर किए । यदि आप अपने डिबेटरों को पूर्ण रिलीज़ रिलीज के अलावा कुछ डिबगिंग जानकारी के साथ कुछ डिबग / डेवलपमेंट फीचर्स के साथ संलग्न करते हैं, तो वे परीक्षण जैसे कि वे चला सकते हैं और सॉफ़्टवेयर चलाते समय अधिक क्रिया आउटपुट उत्पन्न कर सकते हैं। मैंने कम से कम कुछ बड़ी गेम कंपनियों को अल्फा के लिए ऐसा करते देखा है। लेकिन यह अल्फ़ा या आंतरिक परीक्षण जैसी चीज़ के लिए है जहाँ आप वास्तव में एक रिलीज़ बिल्ड के अलावा परीक्षकों को कुछ देने की कोशिश कर रहे हैं। यदि आप वास्तव में एक रिलीज बिल्ड शिप करने की कोशिश कर रहे हैं, तो परिभाषा के अनुसार, यह नहीं होना चाहिए_DEBUG परिभाषित किया गया है या फिर जो वास्तव में एक "डिबग" और "रिलीज़" बिल्ड के बीच अंतर को भ्रमित कर रहा है।

रिलीज से पहले इस कोड को क्यों हटाया जाना है? चेक एक प्रदर्शन नाली के अधिक नहीं हैं और अगर वे विफल होते हैं तो निश्चित रूप से एक समस्या है जो मैं एक अधिक प्रत्यक्ष त्रुटि संदेश के बारे में पसंद करूंगा।

जैसा कि ऊपर बताया गया है, चेक अनिवार्य रूप से एक प्रदर्शन के दृष्टिकोण से तुच्छ नहीं हैं। बहुत से संभावित रूप से तुच्छ हैं, लेकिन फिर भी, मानक लिबास उनका उपयोग करता है और यह कई मामलों में कई लोगों के लिए अस्वीकार्य तरीकों से प्रदर्शन को प्रभावित कर सकता है, अगर, कहते हैं, std::vectorजब तक एक अनुकूलित रिलीज़ बिल्ड माना जाता है, तब तक 4 बार के यादृच्छिक-अभिगम का ले जाना इसकी सीमा की जाँच के कारण कि इसे कभी भी विफल नहीं होना चाहिए।

एक पूर्व टीम में हमें वास्तव में अपने मैट्रिक्स और वेक्टर लाइब्रेरी को कुछ महत्वपूर्ण पथों में शामिल करना था ताकि डिबग बिल्ड को तेजी से चलाया जा सके, क्योंकि उन आरोह बिंदुओं पर एक परिमाण के क्रम से गणित के संचालन को धीमा कर रहे थे जहां यह था 15 मिनट तक प्रतीक्षा करने की आवश्यकता होने से पहले हमें कोड ऑफ इंट्रेस्ट का पता लगाना चाहिए। मेरे सहकर्मी वास्तव में सिर्फ हटाना चाहते थेassertsएकमुश्त क्योंकि उन्होंने पाया कि सिर्फ ऐसा करने से फर्क पड़ता है। इसके बजाय हम बस आलोचनात्मक डिबग रास्तों को बनाने से बचते रहे। जब हमने उन महत्वपूर्ण रास्तों को सीधे सीमा-जाँच से गुजरे बिना वेक्टर / मैट्रिक्स डेटा का उपयोग किया, तो पूर्ण ऑपरेशन (जिसमें सिर्फ वेक्टर / मैट्रिक्स गणित से अधिक शामिल था) को मिनटों से घटाकर सेकंड करने की आवश्यकता थी। तो यह एक चरम मामला है, लेकिन निश्चित रूप से मुखर हमेशा प्रदर्शन के दृष्टिकोण से नगण्य नहीं होते हैं, करीब भी नहीं।

लेकिन यह भी सिर्फ जिस तरह assertsसे डिजाइन किए गए हैं। यदि उनके पास बोर्ड में इतना बड़ा प्रदर्शन प्रभाव नहीं होता है, तो मैं इसका पक्ष रख सकता हूं यदि वे एक डिबग बिल्ड फीचर से अधिक के रूप में डिज़ाइन किए गए थे या हम उपयोग कर सकते हैं vector::atजिसमें रिलीज बिल्ड में सीमा की जाँच भी शामिल है और सीमा से बाहर फेंकता है। पहुँच, जैसे (अभी तक एक बड़ी प्रदर्शन हिट के साथ)। लेकिन वर्तमान में मैं उनके डिजाइन को बहुत अधिक उपयोगी मानता हूं, मेरे मामलों में उनके विशाल प्रदर्शन प्रभाव को देखते हुए, डिबग-बिल्ड-ओनली फीचर के रूप में, जिसे NDEBUGपरिभाषित करते समय छोड़ा जाता है। जिन मामलों में मैंने कम से कम साथ काम किया है, उनके लिए यह रिलीज के निर्माण के लिए एक बड़ा अंतर है कि यह पवित्रता की जांच को बाहर कर सकता है जो वास्तव में पहले स्थान पर कभी असफल नहीं होना चाहिए।

vector::at बनाम vector::operator[]

मुझे लगता है कि इन दोनों विधियों का भेद इसके दिल के साथ-साथ विकल्प: अपवादों पर भी मिलता है। vector::operator[]कार्यान्वयन आम तौर assertपर यह सुनिश्चित करने के लिए होता है कि सीमा से बाहर एक सदिश-सीमा त्रुटि को ट्रिगर करेगा जब किसी वेक्टर को सीमा से बाहर करने का प्रयास किया जाएगा। लेकिन पुस्तकालय के कार्यान्वयनकर्ता इस धारणा के साथ करते हैं कि यह एक अनुकूलित रिलीज बिल्ड में एक पैसा भी खर्च नहीं करेगा।

इस बीच vector::atप्रदान किया जाता है जो हमेशा सीमा की जाँच करता है और रिलीज़ बिल्ड में भी फेंकता है, लेकिन इसमें उस पर एक प्रदर्शन जुर्माना होता है, जहाँ मुझे अक्सर उपयोग की vector::operator[]तुलना में कहीं अधिक कोड दिखाई देता है vector::at। C ++ का बहुत सारा डिज़ाइन "भुगतान के लिए जो आप उपयोग करते हैं / ज़रूरत है" का विचार गूँजता है, और बहुत से लोग अक्सर एहसान करते हैं operator[], जो रिलीज बिल्ड में सीमा की जाँच के साथ परेशान नहीं करता है, इस धारणा के आधार पर कि वे डॉन नहीं करते हैं 'टी की जरूरत है उनके अनुकूलित रिलीज बनाता है में जाँच की सीमा। अचानक अगर रिलीज बिल्ड में जोर दिया गया, तो इन दोनों का प्रदर्शन समान होगा, और वेक्टर का उपयोग हमेशा गतिशील सरणी की तुलना में धीमा होगा। तो अभिकथन के डिजाइन और लाभ का एक बड़ा हिस्सा इस विचार पर आधारित है कि वे एक रिलीज बिल्ड में मुक्त हो जाते हैं।

release_assert

इन इरादों की खोज के बाद यह दिलचस्प है। स्वाभाविक रूप से सभी के उपयोग के मामले अलग-अलग होंगे, लेकिन मुझे लगता है कि मुझे कुछ उपयोग मिलेगा release_assertजिसके लिए चेक करता है और रिलीज बिल्ड में भी लाइन नंबर और त्रुटि संदेश दिखाने वाले सॉफ़्टवेयर को क्रैश कर देगा।

यह मेरे मामले में कुछ अस्पष्ट मामलों के लिए होगा जहां मैं नहीं चाहता कि सॉफ्टवेयर इनायत से उबर जाए क्योंकि यह अपवाद है। मैं चाहता हूं कि यह उन मामलों में भी दुर्घटनाग्रस्त हो जाए ताकि उपयोगकर्ता को रिपोर्ट करने के लिए एक लाइन नंबर दिया जा सके जब सॉफ्टवेयर को कुछ ऐसा हुआ जो कभी भी नहीं होना चाहिए, फिर भी प्रोग्रामर त्रुटियों के लिए विवेक जांच के दायरे में, बाहरी इनपुट त्रुटियों की तरह नहीं अपवाद, लेकिन रिलीज में इसकी लागत के बारे में चिंता किए बिना काफी सस्ता है।

वास्तव में कुछ मामले हैं जहां मुझे एक पंक्ति संख्या और त्रुटि संदेश के साथ एक कठिन दुर्घटना मिल जाएगी, जो कि एक फेंके गए अपवाद से इनायत से उबरने के लिए बेहतर होगा जो एक रिलीज में रखने के लिए काफी सस्ता हो सकता है। और कुछ ऐसे मामले हैं, जहां एक अपवाद से उबरना असंभव है, जैसे कि किसी मौजूदा से पुनर्प्राप्त करने का प्रयास करने में त्रुटि हुई। वहाँ मुझे एक release_assert(!"This should never, ever happen! The software failed to fail!");स्वाभाविक रूप से एक सही फिट मिल जाएगा जो कि सस्ते में गंदगी हो जाएगा क्योंकि चेक पहले स्थान पर एक असाधारण पथ के अंदर किया जाएगा और सामान्य निष्पादन पथ में कुछ भी खर्च नहीं करेगा।


मेरा इरादा तीसरे पक्ष के कोड में जोर डालने में सक्षम नहीं था, स्पष्ट संपादन देखें। मेरी टिप्पणी का उद्धरण मेरे प्रश्न के संदर्भ को छोड़ देता है: Additionally, the performance argument for me only counts when it is a measurable problem.इसलिए विचार यह है कि केस के आधार पर केस का फैसला किया जाए, जब रिलीज से बाहर निकालने के लिए।
कोई नहीं

अंतिम टिप्पणी के साथ समस्याओं में से एक यह है कि मानक पुस्तकालय उसी का उपयोग करता है assertजो उसी _DEBUG/NDEBUGप्रीप्रोसेसर पर निर्भर करता है जैसा कि आप assertमैक्रो का उपयोग करते समय उपयोग करते हैं । इसलिए मानक लिबास के लिए सक्षम किए बिना कोड के एक टुकड़े के लिए चुनिंदा रूप से दावे को सक्षम करने का कोई तरीका नहीं है, उदाहरण के लिए, मान लें कि यह मानक लिबास का उपयोग करता है।

एसटीएल पुनरावृत्ति जाँच है जिसे आप अलग से अक्षम कर सकते हैं जो कुछ कथनों को अक्षम करता है, लेकिन सभी को नहीं।

यह मूल रूप से एक मोटे उपकरण है, दानेदार नहीं है, और हमेशा उस डिज़ाइन को रिलीज़ में अक्षम होने के इरादे से, इसलिए आपकी टीम के साथी इसे महत्वपूर्ण क्षेत्रों में इस धारणा के खिलाफ उपयोग कर सकते हैं कि यह रिलीज़ के प्रदर्शन को प्रभावित नहीं करने वाला है, मानक पुस्तकालय इसका उपयोग करता है महत्वपूर्ण क्षेत्रों में रास्ता, अन्य तीसरे पक्ष के लिबास इसका उपयोग उस तरह से करते हैं, आदि और जब आप कुछ चाहते हैं, तो आप कोड के एक टुकड़े को और अधिक विशेष रूप से अक्षम कर सकते हैं / सक्षम कर सकते हैं और दूसरे को नहीं, हम फिर से कुछ के अलावा देखने के लिए वापस आ रहे हैं assert

vector::operator[]और vector::at, उदाहरण के लिए, व्यावहारिक रूप से एक ही प्रदर्शन होगा यदि अभिकारकों को रिलीज़ बिल्ड में सक्षम किया गया था, और operator[]प्रदर्शन के दृष्टिकोण से अब और उपयोग करने का कोई मतलब नहीं होगा क्योंकि यह वैसे भी जाँच कर रहा होगा।

2

मैं रूबी में कोडिंग कर रहा हूं, सी / सी ++ नहीं, और इसलिए मैं एसेर्ट्स और अपवादों के बीच अंतर के बारे में नहीं बोलूंगा लेकिन मैं इसके बारे में बात करना चाहूंगा जो रनटाइम को रोकते हैं । मैं ऊपर दिए गए अधिकांश जवाबों से असहमत हूं, क्योंकि एक बैकट्रेस को प्रिंट करने के साथ प्रोग्राम को रोकना मेरे लिए रक्षात्मक प्रोग्रामिंग तकनीक के रूप में ठीक काम करता है
यदि मुखर दिनचर्या के लिए कोई रास्ता है (बिल्कुल कोई फर्क नहीं पड़ता कि यह कैसे वाक्यविन्यास लिखा गया है और अगर "मुखर" शब्द का उपयोग किया जाता है या प्रोग्रामिंग भाषा या डीएसएल में मौजूद है) तो इसका मतलब है कि कुछ काम किया जाना चाहिए और उत्पाद तुरंत "जारी, उपयोग-तैयार" से "पैच की आवश्यकता" पर वापस चला जाता है - अब या तो इसे वास्तविक अपवाद हैंडलिंग के लिए फिर से लिखें या एक बग को ठीक करें जिससे गलत डेटा दिखाई दे।

मेरा मतलब है कि Assert एक ऐसी चीज नहीं है जिसे आपको साथ रहना चाहिए और बार-बार कॉल करना चाहिए - यह एक स्टॉप सिग्नल है जो इंगित करता है कि आपको इसे फिर से कभी नहीं बनाने के लिए smth करना चाहिए। और यह कहना कि "रिलीज बिल्ड में जोर नहीं होना चाहिए" यह कहने जैसा है कि "रिलीज बिल्ड में बग नहीं होने चाहिए" - यार, यह लगभग असंभव है, इसके साथ सौदा करें।
या उनके बारे में सोचें कि "असफल उपयोगकर्ता द्वारा बनाई गई असफलता और अंतिम उपयोगकर्ता द्वारा चलाए जा रहे हैं" के बारे में। आप उन सभी चीजों की भविष्यवाणी नहीं कर सकते हैं जो उपयोगकर्ता आपके कार्यक्रम के साथ करने वाला है, लेकिन अगर बहुत गंभीर गलत हो जाता है तो इसे रोक देना चाहिए - यह उसी तरह है जैसे आप पाइपलाइन का निर्माण करते हैं - आप प्रक्रिया को रोकते हैं और प्रकाशित नहीं करते हैं, क्या आप ? जोर उपयोगकर्ता को आपकी मदद के लिए रुकने, रिपोर्ट करने और प्रतीक्षा करने के लिए मजबूर करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.