जैसा कि दूसरों ने बताया, 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!");स्वाभाविक रूप से एक सही फिट मिल जाएगा जो कि सस्ते में गंदगी हो जाएगा क्योंकि चेक पहले स्थान पर एक असाधारण पथ के अंदर किया जाएगा और सामान्य निष्पादन पथ में कुछ भी खर्च नहीं करेगा।