क्या यह उचित है कि हर एक डेरेफ़र्ड पॉइंटर को पहरा दिया जाए?


65

एक नई नौकरी में, मुझे इस तरह कोड के लिए कोड समीक्षाओं में झंडी मिल रही है:

PowerManager::PowerManager(IMsgSender* msgSender)
  : msgSender_(msgSender) { }

void PowerManager::SignalShutdown()
{
    msgSender_->sendMsg("shutdown()");
}

मुझे बताया गया है कि अंतिम विधि को पढ़ना चाहिए:

void PowerManager::SignalShutdown()
{
    if (msgSender_) {
        msgSender_->sendMsg("shutdown()");
    }
}

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

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

क्या यह आवश्यक है कि कोडिंग मानक के लिए यह आवश्यक हो कि किसी फ़ंक्शन में प्रत्येक एकल पॉइंटर को NULLपहले भी निजी डेटा सदस्यों के लिए चेक किया जाए ? (नोट: कुछ संदर्भ देने के लिए, हम एक उपभोक्ता इलेक्ट्रॉनिक्स डिवाइस बनाते हैं, न कि एक एयर ट्रैफिक कंट्रोल सिस्टम या कुछ अन्य 'विफलता-समान-लोग-डाई' उत्पाद।)

संपादित करें : उपरोक्त उदाहरण में, msgSender_सहयोगी वैकल्पिक नहीं है। यदि यह कभी है NULL, तो यह बग को इंगित करता है। निर्माणकर्ता में इसे पारित करने का एकमात्र कारण PowerManagerमॉक IMsgSenderसबक्लास के साथ परीक्षण किया जा सकता है ।

सारांश : इस सवाल के कुछ शानदार जवाब थे, सभी का धन्यवाद। मैंने मुख्य रूप से इसकी संक्षिप्तता के कारण @aronps से स्वीकार किया। ऐसा प्रतीत होता है कि काफी व्यापक सामान्य समझौता है:

  1. हर एक dereferenced पॉइंटर के NULLलिए अनिवार्य गार्ड ओवरकिल है, लेकिन
  2. आप (यदि संभव हो तो) या constपॉइंटर के बजाय एक संदर्भ का उपयोग करके पूरी बहस को साइड-स्टेप कर सकते हैं
  3. assertबयानों को NULLसत्यापित करने के लिए गार्ड के लिए एक अधिक प्रबुद्ध विकल्प है कि एक फ़ंक्शन के पूर्व शर्त मिलते हैं।

14
एक मिनट के लिए मत सोचो कि गलतियाँ जूनियर प्रोग्रामर का डोमेन हैं। अनुभव के सभी स्तरों के डेवलपर्स के 95% कुछ समय में एक बार कुछ। शेष 5% अपने दांतों के माध्यम से झूठ बोल रहे हैं।
ब्लरफ्ल

56
अगर मैंने किसी को एक ऐसा कोड लिखा देखा जो अशक्त और चुपचाप विफल हो जाता है, तो मैं उन्हें मौके पर पहुंचाना चाहता हूं।
विंस्टन इर्वर्ट

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

1
+1, बहुत दिलचस्प सवाल। मेरे उत्तर के अलावा, मैं यह भी बताऊंगा कि जब आपको कोड लिखना होता है तो यूनिट टेस्ट को समायोजित करना किसका उद्देश्य होता है, जो आप वास्तव में कर रहे हैं वह सुरक्षा की झूठी भावना के लिए बढ़ा हुआ जोखिम है (कोड की अधिक पंक्तियाँ = कीड़े के लिए अधिक संभावनाएं)। संदर्भों का उपयोग करने के लिए रीडायरेक्ट करना न केवल कोड की पठनीयता में सुधार करता है, बल्कि कोड (और परीक्षण) की मात्रा को भी कम करता है जिसे आपको यह साबित करने के लिए लिखना होगा कि यह काम करता है।
सेठ

6
@, मुझे यकीन है कि एक मौन असफल के लिए उपयुक्त मामले हैं। लेकिन किसी को चुप डालता सामान्य अभ्यास के रूप में में विफल रहता है (जब तक कि एक दायरे जहां यह समझ बनाने में काम कर), मैं वास्तव में नहीं है एक परियोजना वे में कोड लगा रहे हैं पर काम करना चाहते हैं।
विंस्टन Ewert

जवाबों:


66

यह 'अनुबंध' पर निर्भर करता है:

यदि PowerManager MUST के पास वैध है IMsgSender, तो कभी भी अशक्त होने की जांच न करें, इसे जल्द ही मर जाने दें।

दूसरी ओर, यह तो हो सकता है एक है IMsgSender, तो आप, हर बार जब आप का उपयोग करने की जांच करने के रूप में सरल रूप में की जरूरत है।

जूनियर प्रोग्रामर की कहानी के बारे में अंतिम टिप्पणी, समस्या वास्तव में परीक्षण प्रक्रियाओं की कमी है।


4
एक बहुत ही रसीले जवाब के लिए, जो मुझे लगता है कि बहुत अधिक रकम देता है: "यह निर्भर करता है ..." आपको यह भी कहने की हिम्मत थी कि "कभी भी अशक्त होने की जांच न करें" ( यदि नल अमान्य है)। एक रखने assert()हर सदस्य समारोह है कि एक सूचक dereferences में एक समझौता है कि संभावना बहुत से लोगों को शांत जाएगा, लेकिन फिर भी है कि मेरे पास 'सट्टा व्यामोह' की तरह लगता है। मेरी नियंत्रण करने की क्षमता से परे चीजों की सूची अनंत है, और एक बार जब मैं खुद को उनके बारे में चिंता करना शुरू करने की अनुमति देता हूं, तो यह वास्तव में फिसलन ढलान बन जाता है। मेरे परीक्षणों, मेरे सहकर्मियों और मेरे डिबगर पर भरोसा करना सीखना- मुझे रात में बेहतर सोने में मदद मिली है।
ईवेडफ्लो

2
जब आप कोड पढ़ रहे हों तो यह समझने में बहुत मददगार हो सकता है कि कोड कैसे काम करने वाला है। मैंने कभी भी एक कोडबेस को एनक्रिप्ट नहीं किया है जिसने मुझे जाना है 'काश यह सभी जगह पर इन सभी का दावा नहीं करता।', लेकिन मैंने बहुत कुछ देखा है जहां मैंने इसके विपरीत कहा था।
क्रिस्टोफ प्रोवोस्ट

1
सादा और सरल, यह प्रश्न का सही उत्तर है।
मैथ्यू अज्किमोव

2
यह निकटतम सही उत्तर है, लेकिन मैं 'अशक्त के लिए जाँच कभी नहीं' के साथ सहमत नहीं हो सकता, हमेशा अमान्य मापदंडों के लिए जाँच करें कि वे एक सदस्य चर को सौंपा जाएगा।
जेम्स

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

77

मुझे लगता है कि कोड को पढ़ना चाहिए:

PowerManager::PowerManager(IMsgSender* msgSender)
  : msgSender_(msgSender)
{
    assert(msgSender);
}

void PowerManager::SignalShutdown()
{
    assert(msgSender_);
    msgSender_->sendMsg("shutdown()");
}

यह वास्तव में NULL की सुरक्षा से बेहतर है, क्योंकि यह बहुत स्पष्ट करता है कि फ़ंक्शन को कभी भी msgSender_NULL नहीं कहा जाना चाहिए । यह भी सुनिश्चित करता है कि ऐसा होने पर आप नोटिस करेंगे।

आपके सहकर्मियों की साझा "समझदारी" अप्रत्याशित परिणाम के साथ चुपचाप इस त्रुटि को अनदेखा कर देगी।

सामान्य बग्स को ठीक करना आसान होता है यदि वे अपने कारण के करीब पाए जाते हैं। इस उदाहरण में प्रस्तावित NULL गार्ड बंद नहीं होने वाले संदेश को ले जाएगा, जिसके परिणामस्वरूप ध्यान देने योग्य बग हो सकता है या नहीं। आपके पास कार्य करने के लिए एक कठिन समय होता है जब वह SignalShutdownकार्य पूरा हो जाता है, तो सीधे-सीधे बांकी बैकरेस या कोर डंप का निर्माण होता है SignalShutdown()

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


10
कॉलिंग एस्टर और ओपी के कोड उदाहरण के बीच बड़ा अंतर यह है कि एसेर केवल डीबग बिल्ड (#define NDEBUG) में सक्षम होता है, जब उत्पाद ग्राहक के हाथों में हो जाता है, और डिबग अक्षम हो जाता है, और कोड पाथ का कभी न-योजित संयोजन छोड़ने के लिए निष्पादित होता है पॉइंटर नल भले ही विचाराधीन फ़ंक्शन निष्पादित हो, लेकिन मुखर आपको कोई सुरक्षा प्रदान नहीं करता है।
ATK

17
संभवतः आपने ग्राहक को भेजने से पहले बिल्ड का परीक्षण किया होगा, लेकिन हां, यह एक संभावित जोखिम है। समाधान हालांकि आसान हैं: या तो केवल सक्षम किए गए एशर्ट के साथ जहाज (जो कि वैसे भी आपके द्वारा परीक्षण किया गया संस्करण है) या इसे अपने स्वयं के मैक्रो के साथ बदलें जो डिबग मोड में दावा करता है और रिलीज मोड में सिर्फ लॉग, बैकट्रैक, एक्सिट, ... लॉग करता है।
क्रिस्टोफ प्रोवोस्ट

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

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

2
@ नाम: एम्बेडेड सिस्टम के साथ मेरे अनुभव में, सॉफ्टवेयर और हार्डवेयर को हमेशा के लिए डिज़ाइन किया गया है जो कि किसी डिवाइस को अनुपयोगी बनाने के लिए अत्यंत कठिन है। अधिकांश मामलों में, एक हार्डवेयर वॉचडॉग होता है, जो सॉफ़्टवेयर को चलाने से रोकने पर डिवाइस को पूर्ण रीसेट करने के लिए बाध्य करता है।
बार्ट वैन इनगेन शेनॉ नो

30

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

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

इसके अलावा - यदि आप निश्चित हैं कि तर्क कभी भी अशक्त नहीं हो सकता है, तो कक्षा के आपके उपयोग के आधार पर संदर्भों का उपयोग करने पर विचार करें। अन्यथा, कच्चे सूचक के उपयोग std::unique_ptrया std::shared_ptrबदले में विचार करें ।


11

नहीं, पॉइंटर होने के लिए हर पॉइंटर डेरेफेरेंस की जांच करना उचित नहीं है NULL

Null- पॉइंटर चेक फ़ंक्शन तर्कों (निर्माण तर्क सहित) पर मूल्यवान हैं ताकि यह सुनिश्चित किया जा सके कि कोई वैकल्पिक पैरामीटर प्रदान नहीं किया गया है या नहीं, और उचित कार्रवाई प्रदान करने के लिए वे क्लास के इनवॉयलर को उजागर करने के बाद किसी वर्ग के अपरिवर्तनीय की जांच करने के लिए मूल्यवान हैं। लेकिन अगर एक पॉइंटर के NULL बनने का एकमात्र कारण बग का अस्तित्व है, तो जाँच का कोई मतलब नहीं है। यह बग आसानी से पॉइंटर को दूसरे अमान्य मान पर सेट कर सकता है।

अगर मैं तुम्हारी जैसी स्थिति का सामना कर रहा था, तो मैं दो सवाल पूछूंगा:

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

9

यह उदाहरण ऑब्जेक्ट जीवनकाल के बारे में अधिक लगता है कि इनपुट पैरामीटर शून्य है या नहीं। चूँकि आप उल्लेख करते हैं कि हमेशा एक वैध PowerManagerहोना चाहिए , सूचक द्वारा तर्क को पारित करना (जिससे एक शून्य सूचक की संभावना की अनुमति देता है) मुझे एक डिजाइन दोष के रूप में हमला करता है must।IMsgSender

इस तरह की स्थितियों में, मैं इंटरफ़ेस बदलना पसंद करूंगा, ताकि कॉलर की आवश्यकताओं को भाषा द्वारा लागू किया जाए:

PowerManager::PowerManager(const IMsgSender& msgSender)
  : msgSender_(msgSender) {}

void PowerManager::SignalShutdown() {
    msgSender_->sendMsg("shutdown()");
}

इस तरह से यह कहते हुए कि यह पूरे जीवनकाल के लिए PowerManagerएक संदर्भ रखने की जरूरत है IMsgSender। यह, बदले में, एक अंतर्निहित आवश्यकता को भी स्थापित करता है जो कि IMsgSenderअधिक समय तक जीवित रहना चाहिए PowerManager, और किसी भी अशक्त सूचक की जाँच या अंदर की आवश्यकता की उपेक्षा करता है PowerManager

आप स्मार्ट पॉइंटर (बूस्ट या सी ++ 11 के माध्यम से) का उपयोग करके, स्पष्ट रूप IMsgSenderसे अधिक समय तक जीने के लिए मजबूर करने के लिए भी लिख सकते हैं PowerManager:

PowerManager::PowerManager(std::shared_ptr<IMsgSender> msgSender) 
  : msgSender_(msgSender) {}

void PowerManager::SignalShutdown() {
    // Here, we own a smart pointer to IMsgSender, so even if the caller
    // destroys the original pointer, we still have a valid copy
    msgSender_->sendMsg("shutdown()");
}

इस विधि को पसंद किया जाता है यदि यह संभव है कि IMsgSenderजीवन भर की गारंटी से अधिक होने की गारंटी नहीं दी जा सकती PowerManager(यानी, x = new IMsgSender(); p = new PowerManager(*x);)।

† संकेत के संबंध में: प्रचंड अशांति की जाँच से कोड को पढ़ना मुश्किल हो जाता है, और यह स्थिरता में सुधार नहीं करता है (यह स्थिरता की उपस्थिति में सुधार करता है, जो बहुत बुरा है)।

कहीं, किसी को स्मृति रखने के लिए पता मिला IMsgSender। यह सुनिश्चित करने के लिए फ़ंक्शन की ज़िम्मेदारी है कि आवंटन सफल हुआ (पुस्तकालय रिटर्न मानों की जांच करना या std::bad_allocअपवादों को ठीक से संभालना ), ताकि अमान्य पॉइंटर्स के आसपास से न गुजरें।

चूंकि PowerManagerयह खुद का मालिक नहीं है IMsgSender(यह थोड़ी देर के लिए इसे उधार ले रहा है), यह उस मेमोरी को आवंटित करने या नष्ट करने के लिए जिम्मेदार नहीं है। यह एक और कारण है कि मैं संदर्भ को क्यों पसंद करता हूं।

†† चूंकि आप इस नौकरी में नए हैं, इसलिए मुझे उम्मीद है कि आप मौजूदा कोड को हैक कर रहे हैं। तो डिजाइन दोष से, मेरा मतलब है कि दोष उस कोड में है जिसके साथ आप काम कर रहे हैं। इस प्रकार, जो लोग आपके कोड को ध्वजांकित कर रहे हैं क्योंकि यह अशक्त बिंदुओं के लिए जाँच नहीं कर रहा है, वे वास्तव में कोड लिखने के लिए खुद को झंडी दिखा रहे हैं, जिन्हें बिंदु की आवश्यकता है :)


1
कच्चे पॉइंटर्स का उपयोग करने में कभी-कभी कुछ भी गलत नहीं होता है। Std :: share_ptr एक चांदी की गोली नहीं है और एक तर्क सूची में इसका उपयोग मैला इंजीनियरिंग के लिए एक इलाज है, हालांकि मुझे लगता है कि इसे 'लेट' माना जाता है जब भी संभव हो इसका उपयोग करें। अगर आपको ऐसा लगता है तो जावा का उपयोग करें।
जेम्स

2
मैंने नहीं कहा कि कच्चे पॉइंटर्स खराब हैं! उनका स्थान निश्चित रूप से है। हालांकि, यह C + + है , संदर्भ (और साझा संकेत, अब) एक कारण के लिए भाषा का हिस्सा हैं। उनका उपयोग करें, वे आपके सफल होने का कारण बनेंगे।
सेठ

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

8

अपवादों की तरह, गार्ड की स्थिति केवल तभी उपयोगी होती है जब आप जानते हैं कि त्रुटि से उबरने के लिए क्या करना है या यदि आप अधिक सार्थक अपवाद संदेश देना चाहते हैं।

एक त्रुटि (चाहे वह अपवाद या गार्ड-चेक के रूप में पकड़ी गई हो) को निगल लेना, केवल सही बात है जब त्रुटि मायने नहीं रखती है। मेरे लिए त्रुटियों को निगल जाने के लिए सबसे आम स्थान त्रुटि लॉगिंग कोड में है - आप किसी एप्लिकेशन को क्रैश नहीं करना चाहते क्योंकि आप एक स्थिति संदेश लॉग करने में असमर्थ थे।

किसी भी कार्य को कहा जाता है, और यह वैकल्पिक व्यवहार नहीं है, इसे जोर से विफल होना चाहिए, चुपचाप नहीं।

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


7

जैसा कि अन्य ने उल्लेख किया है, यह इस बात पर निर्भर करता है कि वैध रूप सेmsgSender हो सकता है या नहीं । निम्नलिखित मानता है कि इसे कभी भी पूरा नहीं होना चाहिए । NULL

void PowerManager::SignalShutdown()
{
    if (!msgSender_)
    {
       throw SignalException("Shut down failed because message sender is not set.");
    }

    msgSender_->sendMsg("shutdown()");
}

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

एक शून्य की जाँच नहीं करके जूनियर ने कहर बरपाया। क्या होगा अगर यह अपरिभाषित अवस्था में चलने के लिए कोड का यह टुकड़ा कहर बरपाता है (डिवाइस चालू है लेकिन प्रोग्राम "सोचता है" यह बंद है)? शायद कार्यक्रम का एक और हिस्सा ऐसा कुछ करेगा जो केवल तभी सुरक्षित है जब डिवाइस बंद हो।

या तो इन तरीकों से मौन विफलताओं से बचेंगे:

  1. इस उत्तर द्वारा सुझाए अनुसार उपयोग करें , लेकिन सुनिश्चित करें कि वे उत्पादन कोड में चालू हैं। यह, निश्चित रूप से, समस्याओं का कारण बन सकता है अगर अन्य जोर देकर कहा गया है कि वे उत्पादन में बंद हो जाएंगे।

  2. एक अपवाद फेंको अगर यह शून्य है।


5

मैं कंस्ट्रक्टर में नल फंसने से सहमत हूं। इसके अलावा, यदि सदस्य हेडर में घोषित किया गया है:

IMsgSender* const msgSender_;

तब सूचक को आरंभीकरण के बाद नहीं बदला जा सकता है, इसलिए यदि यह निर्माण में ठीक था, तो यह ऑब्जेक्ट के जीवनकाल के लिए ठीक होगा। (वस्तु बताया करने के लिए होगा नहीं स्थिरांक हो।)


यह बहुत अच्छी सलाह है, धन्यवाद! इतना अच्छा, वास्तव में, मुझे खेद है कि मैं इसे किसी भी उच्च वोट नहीं कर सकता। यह कथित प्रश्न का सीधा उत्तर नहीं है, लेकिन यह पॉइंटर के गलती से बनने की किसी भी संभावना को खत्म करने का एक शानदार तरीका है NULL
evadeflow

@evadeflow मैंने सोचा "मैं हर किसी से सहमत हूं" सवाल का मुख्य जोर दिया। चियर्स हालांकि! ;-)
ग्रिम द ओपिनर

मेरे लिए इस बिंदु पर स्वीकृत जवाब को बदलना थोड़ा कठिन होगा, जिस तरह से यह सवाल था। लेकिन मुझे लगता है कि यह सलाह बहुत मायने रखती है, और मुझे खेद है कि मैंने खुद इसके बारे में नहीं सोचा। एक constपॉइंटर के साथ , assert()कंस्ट्रक्टर के बाहर की आवश्यकता नहीं है , इसलिए यह उत्तर @Kristof Provost की तुलना में थोड़ा बेहतर है (जो कि बकाया भी था, लेकिन साथ ही साथ कुछ हद तक अप्रत्यक्ष रूप से प्रश्न को संबोधित किया।) मुझे आशा है कि अन्य इसे वोट करेंगे, क्योंकि यह तब से है। वास्तव assertमें हर विधि में कोई मतलब नहीं है जब आप सिर्फ पॉइंटर बना सकते हैं const
23

@evadeflow लोग रेप के लिए केवल क्वेस्टिन की यात्रा करते हैं, अब यह उत्तर दिया गया है कि कोई भी इसे फिर से नहीं देखेगा। ;-) मैं केवल इसलिए पॉप-अप हुआ क्योंकि यह पॉइंटर्स के बारे में एक सवाल था और मैं खूनी "हमेशा सभी चीजों के लिए स्मार्ट पॉइंटर्स का उपयोग करता हूं" ब्रिगेड पर नज़र रख रहा हूं।
ग्रिम द ओपिनर

3

यह एकमुश्त खतरनाक है!

मैंने एक वरिष्ठ डेवलपर के तहत एक सी कोडबेस में शोडेस्टेस्ट "मानकों" के साथ काम किया, जो एक ही चीज़ के लिए धक्का देते थे, नेत्रहीन रूप से सभी बिंदुओं की जांच करने के लिए। डेवलपर इस तरह की चीजों को समाप्त करेगा:

// Pre: vertex should never be null.
void transform_vertex(Vertex* vertex, ...)
{
    // Inserted by my "wise" co-worker.
    if (!vertex)
        return;
    ...
}

मैंने एक बार इस तरह के एक समारोह में पूर्व शर्त के इस तरह के एक चेक को हटाने की कोशिश की और यह assertदेखने के लिए कि क्या होगा।

मेरे आतंक के लिए, मुझे कोडबेस में कोड की हजारों लाइनें मिलीं, जो इस फ़ंक्शन को अशक्त कर रही थीं, लेकिन जहां डेवलपर्स, भ्रमित होने की संभावना थी, चारों ओर काम किया और चीजों को काम करने तक बस अधिक कोड जोड़ा।

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

इसने इस + समय की तरह कोड के दो प्रतीत होते-निर्दोष रेखाएं और एक हजार संचित कीड़े को समाप्त करने के लिए एक टीम बनाई।

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

केवल उन स्थानों पर नेत्रहीन रूप से नल के लिए जांच करें जहां एक नल सूचक एक पूर्व शर्त का उल्लंघन करता है, मेरे लिए, पूरी तरह से पागलपन है, जब तक कि आपका सॉफ्टवेयर जोरदार विफलताओं के खिलाफ मिशन-महत्वपूर्ण है और उत्पादन क्रैश है कि इस परिदृश्य की क्षमता बेहतर है।

क्या यह आवश्यक है कि कोडिंग मानक के लिए यह आवश्यक है कि फ़ंक्शन में प्रत्येक एकल पॉइंटर को NULL प्रथम-यहां तक ​​कि निजी सदस्यों के लिए चेक किया जाए?

तो मैं कहूंगा, बिल्कुल नहीं। यह "सुरक्षित" भी नहीं है। यह बहुत अच्छी तरह से विपरीत हो सकता है और आपके कोडबेस में सभी प्रकार के कीड़े को मुखौटा कर सकता है, जो वर्षों में सबसे भयानक परिदृश्यों को जन्म दे सकता है।

assertयहाँ जाने का रास्ता है। पूर्व शर्त के उल्लंघन पर किसी का ध्यान नहीं जाने दिया जाना चाहिए, अन्यथा मर्फी का कानून आसानी से अंदर आ सकता है।


1
"assert" जाने का रास्ता है - लेकिन याद रखें कि किसी भी आधुनिक प्रणाली पर, एक पॉइंटर के माध्यम से प्रत्येक मेमोरी एक्सेस में एक अशक्त-सूचक एस्टर है जो हार्डवेयर में बनाया गया है। तो "assert (p! = NULL); वापसी * ​​p;" यहां तक ​​कि मुखर ज्यादातर व्यर्थ है।
gnasher729

@ gnasher729 आह, यह एक बहुत ही अच्छी बात है, लेकिन मैं assertएक दस्तावेज़ीकरण तंत्र के रूप में यह देखने के लिए हूं कि क्या पूर्व शर्त हैं और केवल एक गर्भपात के लिए मजबूर करने का तरीका नहीं है। लेकिन मुझे यह भी पसंद है कि मुखर विफलता की प्रकृति जो आपको दिखाती है कि कोड की कौन सी रेखा विफलता का कारण बनी और मुखर स्थिति विफल रही ("दुर्घटना का दस्तावेजीकरण")। काम में आ सकता है अगर हम एक डिबगर के बाहर डिबग बिल्ड का उपयोग करके समाप्त होते हैं और ऑफ-गार्ड को पकड़ लेते हैं।

@ gnasher729 या मुझे इसका एक हिस्सा गलत लग सकता है। क्या इन आधुनिक प्रणालियों से पता चलता है कि स्रोत कोड की कौन सी पंक्ति जिसमें अभिकथन विफल हो गया है? मैं आमतौर पर कल्पना करता हूं कि उन्होंने उस बिंदु पर जानकारी खो दी है और वह केवल segfault / एक्सेस उल्लंघन दिखा सकता है, लेकिन मैं "आधुनिक" से बहुत दूर हूं - अभी भी अपने अधिकांश विकास के लिए विंडोज 7 पर हठी हूं।

उदाहरण के लिए, मैकओएस एक्स और आईओएस पर, यदि आपका ऐप विकास के दौरान एक शून्य पॉइंटर एक्सेस के कारण क्रैश करता है, तो डिबगर आपको कोड की सटीक रेखा बताएगा जहां यह होता है। एक और अजीब पहलू है: कंपाइलर आपको कुछ संदिग्ध करने पर चेतावनी देने की कोशिश करेगा। यदि आप किसी फ़ंक्शन को पॉइंटर पास करते हैं और उसे एक्सेस करते हैं, तो कंपाइलर आपको चेतावनी नहीं देगा कि पॉइंटर NULL हो सकता है, क्योंकि ऐसा अक्सर होता है, आप चेतावनी में डूब जाएंगे। हालाँकि, यदि आप एक तुलना करते हैं अगर (p == NULL) ... तो संकलक मानता है कि एक अच्छा मौका है कि p NULL है,
gnasher729

क्योंकि आपने इसे अन्यथा परीक्षण क्यों किया होगा, इसलिए यह तब से एक चेतावनी देगा यदि आप इसे बिना परीक्षण के उपयोग करते हैं। यदि आप अपने स्वयं के मुखर जैसे मैक्रो का उपयोग करते हैं, तो आपको इसे लिखने के लिए थोड़ा चतुर होना होगा ताकि "my_assert (p! = NULL," यह एक अशक्त सूचक हो, बेवकूफ! "); * P = 1;" आपको चेतावनी नहीं देता।
gnasher729

2

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

उस ने कहा, कोड एक पारिस्थितिकी तंत्र में रहता है, एक वैक्यूम नहीं। अशक्त-रक्षक व्यवहार C ++ में गैर-मुहावरेदार और आश्चर्यजनक होगा , और इसलिए इसे हानिकारक माना जाना चाहिए। सारांश में, कोई भी C ++ कोड उस तरह से नहीं लिखता है, इसलिए ऐसा न करें! एक प्रति-उदाहरण के रूप में, हालांकि, ध्यान दें कि C या C ++ में कॉलिंग free()या deleteऑन NULLन होने की गारंटी है।


आपके उदाहरण में, यह संभव होगा कि msgSenderगैर-अशक्त कंस्ट्रक्टर में एक जोर दिया जाए । अगर कंस्ट्रक्टर नेmsgSender तुरंत एक विधि को बुलाया , तो ऐसा कोई भी दावा आवश्यक नहीं होगा, क्योंकि यह वैसे भी वहीं दुर्घटनाग्रस्त हो जाएगा। हालांकि, चूंकि यह भविष्य के उपयोग के लिए केवल भंडारण कर रहा है , इसलिए msgSenderस्टैक ट्रेस को देखने से यह स्पष्ट नहीं होगा SignalShutdown()कि मूल्य कैसे आया NULL, इसलिए निर्माणकर्ता में एक जोरदार डिबगिंग को काफी आसान बना देगा।

इससे भी बेहतर, निर्माता को एक const IMsgSender&संदर्भ स्वीकार करना चाहिए , जो संभवतः नहीं हो सकता है NULL


1

कारण यह है कि आप शून्य dereferences से बचने के लिए कहा जाता है यह सुनिश्चित करने के लिए कि आपका कोड मजबूत है। बहुत पहले के जूनियर प्रोग्रामर के उदाहरण केवल उदाहरण हैं। कोई भी दुर्घटना से कोड को तोड़ सकता है और एक अशांति का कारण बन सकता है - विशेष रूप से ग्लोबल्स और क्लास ग्लोबल्स के लिए। सी और सी ++ में यह प्रत्यक्ष मेमोरी प्रबंधन क्षमता के साथ गलती से और भी अधिक संभव है। आपको आश्चर्य हो सकता है, लेकिन इस तरह की बात बहुत बार होती है। यहां तक ​​कि बहुत जानकार, बहुत अनुभवी और बहुत वरिष्ठ डेवलपर्स द्वारा भी।

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

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

आपको एक मजबूत कोड शुद्धता उपकरण का उपयोग करना चाहिए जैसे कि आवरण या दृढ़ करना। और आपको सभी संकलक चेतावनियों को संबोधित करना चाहिए।

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


एक (प्रतीत होता है) अलोकप्रिय स्थिति का समर्थन करने के लिए साहस रखने के लिए +1। मुझे निराशा होती अगर कोई मेरे सहयोगियों का इस पर बचाव नहीं करता (वे बहुत होशियार लोग हैं जो कई वर्षों से एक गुणवत्तापूर्ण उत्पाद डाल रहे हैं)। मुझे यह विचार भी पसंद है कि ऐप्स को "परीक्षण के माहौल में दुर्घटना ... और उत्पादन में इनायत से विफल होना चाहिए।" मुझे विश्वास नहीं हो रहा है कि 'रटे' NULLचेक करना अनिवार्य है, लेकिन मैं अपने कार्यस्थल के बाहर के किसी व्यक्ति की राय सुनने की सराहना करता हूं जो मूल रूप से कह रहा है: "आह। यह बहुत अनुचित नहीं है ।"
14

जब मैं मॉलॉक () के बाद लोगों को NULL के लिए परीक्षण करते देखता हूं तो मुझे गुस्सा आता है। यह बताता है कि वे यह नहीं समझते हैं कि आधुनिक ओएस स्मृति का प्रबंधन कैसे करते हैं।
क्रिस्टोफ प्रोवोस्ट

2
मेरा अनुमान है कि @KristofProvost उन ओएस के बारे में बात कर रहा है जो ओवरकमिट का उपयोग करते हैं, जिसके लिए मॉलोक हमेशा सफल होता है (लेकिन ओएस बाद में आपकी प्रक्रिया को मार सकता है यदि वास्तव में पर्याप्त मेमोरी उपलब्ध नहीं है)। हालांकि, यह एक अच्छा कारण नहीं है कि मॉलॉक पर अशक्त चेक को छोड़ दिया जाए: ओवरकमिट प्लेटफ़ॉर्म पर सार्वभौमिक नहीं है और यहां तक ​​कि अगर यह सक्षम है, तो मॉलॉक के विफल होने के अन्य कारण भी हो सकते हैं (उदाहरण के लिए, लिनक्स पर, एक प्रक्रिया पता स्थान सीमा ulimit के साथ सेट है। )।
जॉन बार्थोलोम्यू

1
जॉन ने क्या कहा मैं वास्तव में ओवरकमिट के बारे में बात कर रहा था। Overcommit को लिनक्स पर डिफ़ॉल्ट रूप से सक्षम किया जाता है (जो कि मेरे बिलों का भुगतान करता है)। मुझे नहीं पता, लेकिन संदेह है, अगर यह विंडोज पर समान है। अधिकांश कैसड में आप वैसे भी दुर्घटनाग्रस्त होने जा रहे हैं, जब तक कि आप बहुत से कोड लिखने के लिए तैयार नहीं हो जाते हैं, कभी भी ऐसी त्रुटियों को संभालने के लिए परीक्षण नहीं किया जाएगा जो लगभग निश्चित रूप से कभी नहीं होने वाली हैं ...
क्रिस्टोफ़ प्रोवोस्ट

2
मुझे जोड़ने दें कि मैंने कभी भी कोड नहीं देखा है (लिनक्स कर्नेल के बाहर, जहां मेमोरी से बाहर वास्तविक रूप से संभव है) जो वास्तव में एक आउट-ऑफ-मेमोरी स्थिति को सही ढंग से संभाल लेगा। कोड के सभी जो मैंने देखा है, वैसे भी बाद में दुर्घटनाग्रस्त हो जाएगा। वह सब जो पूरा करने में समय बर्बाद करना था, वास्तविक समस्या को समझने और छिपाने के लिए कोड को कठिन बना दिया। अशक्त डीरेफरेंस डीबग करना आसान है (यदि आपके पास एक कोर फ़ाइल है)।
क्रिस्टोफ़ प्रोवोस्ट

1

एक के उपयोग सूचक एक के बजाय संदर्भ मुझे बताओ होता है कि msgSenderहै केवल एक विकल्प और यहाँ अशक्त जांच सही होगा। कोड स्निपेट यह तय करने के लिए बहुत धीमा है। हो सकता है कि इसमें अन्य तत्व PowerManagerमूल्यवान हों (या परीक्षण योग्य) ...

सूचक और संदर्भ के बीच चयन करते समय, मैं पूरी तरह से दोनों विकल्पों का वजन करता हूं। अगर मुझे किसी सदस्य के लिए (यहां तक ​​कि निजी सदस्यों के लिए) सूचक का उपयोग करना पड़ता है, तो मुझे if (x)हर बार प्रक्रिया को स्वीकार करना पड़ता है जब मैं इसे लागू करता हूं।


जैसा कि मैंने एक और टिप्पणी में कहीं उल्लेख किया है, ऐसे समय होते हैं जब किसी संदर्भ को इंजेक्ट करना संभव नहीं होता है। एक उदाहरण मैं बहुत कुछ करता हूं, जहां आयोजित वस्तु को धारक के लिए एक संदर्भ की आवश्यकता होती है:
evadeflow

@evadeflow: ठीक है, मैं स्वीकार करता हूं, यह कक्षा के आकार और पॉइंटर सदस्यों की दृश्यता पर निर्भर करता है (जिसे संदर्भ नहीं बनाया जा सकता है), चाहे मैं डेरेफेरिंग से पहले जांच करूं। ऐसे मामलों में जहां कक्षा छोटा और सादा है और पॉइंटर (ओं) निजी हैं, मैं नहीं ...
वोल्फ

0

यह इस बात पर निर्भर करता है कि आप क्या बनना चाहते हैं।

आपने लिखा है कि आप "एक उपभोक्ता इलेक्ट्रॉनिक्स डिवाइस" पर काम कर रहे हैं। यदि, किसी तरह, बग को सेट करके पेश किया msgSender_जाता है NULL, तो क्या आप चाहते हैं

  • डिवाइस पर ले जाने के लिए, लंघन SignalShutdownलेकिन इसके संचालन के बाकी, या जारी है
  • डिवाइस को क्रैश करने के लिए, उपयोगकर्ता को इसे पुनरारंभ करने के लिए मजबूर करना?

शटडाउन सिग्नल के प्रभाव को नहीं भेजे जाने के आधार पर, विकल्प 1 एक व्यवहार्य विकल्प हो सकता है। यदि उपयोगकर्ता अपने संगीत को सुनना जारी रख सकता है, लेकिन प्रदर्शन अभी भी पिछले ट्रैक का शीर्षक दिखाता है, जो डिवाइस के पूर्ण दुर्घटना के लिए बेहतर हो सकता है।

बेशक, अगर आप विकल्प 1 चुनते हैं, तो assert(दूसरों द्वारा अनुशंसित) विकास के दौरान किसी भी तरह की बग रेंगने की संभावना को कम करने के लिए महत्वपूर्ण है। ifअशक्त गार्ड उत्पादन प्रयोग में विफलता शमन के लिए बस नहीं है।

व्यक्तिगत रूप से, मैं प्रोडक्शन बिल्ड के लिए "क्रैश जल्दी" दृष्टिकोण को भी प्राथमिकता देता हूं, लेकिन मैं व्यावसायिक सॉफ्टवेयर विकसित कर रहा हूं जिसे बग के मामले में ठीक किया जा सकता है और आसानी से अपडेट किया जा सकता है। उपभोक्ता इलेक्ट्रॉनिक्स उपकरणों के लिए, यह इतना आसान नहीं हो सकता है।

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