"गोटो" बयान किस तरह के बग की ओर जाता है? क्या कोई ऐतिहासिक महत्वपूर्ण उदाहरण हैं?


103

मैं समझता हूं कि छोरों में नेस्टेड छोरों को तोड़ने के लिए बचाओ; gotoबयान टाल दिया और प्रोग्रामिंग की एक बग का खतरा शैली के रूप में गाली, इस्तेमाल किया जा कभी नहीं करने के लिए किया जाता है।

xkcd ऑल्ट टेक्स्ट: "नील स्टीफेंसन को लगता है कि उनके लेबल 'डेंगो' का नाम प्यारा है"
मूल कॉमिक देखें: http://xkcd.com/292/

क्योंकि मैंने यह जल्दी सीख लिया; मेरे पास वास्तव में कोई अंतर्दृष्टि या अनुभव नहीं है कि gotoवास्तव में किस प्रकार के कीड़े होते हैं । तो हम यहाँ किस बारे में बात कर रहे हैं:

  • अस्थिरता?
  • अप्राप्य या अपठनीय कोड?
  • सुरक्षा कमजोरियां?
  • पूरी तरह से कुछ और?

"गोटो" बयान किस तरह के कीड़े वास्तव में पैदा करते हैं? क्या कोई ऐतिहासिक महत्वपूर्ण उदाहरण हैं?


33
क्या आपने इस विषय पर दीजकस्ट्रा के मूल लघु पेपर को पढ़ा है? (यह एक हाँ / कोई सवाल नहीं है, और एक असमान तात्कालिक "हाँ" के अलावा कोई भी उत्तर "नहीं" है।)
जॉन आर। स्ट्रॉहम

2
मैं एक अलार्म से बाहर निकलने लगता है जब कुछ भयावह विफलता होती है। जहाँ से तुम कभी नहीं लौटोगे। बिजली की विफलता, गायब उपकरणों या फ़ाइलों की तरह। "त्रुटि गोटो पर" के कुछ प्रकार ... लेकिन मुझे लगता है कि आजकल अधिकांश "लगभग तबाही" त्रुटियों को "कोशिश - पकड़" द्वारा नियंत्रित किया जा सकता है।
लीन

13
किसी ने अभी तक गणना किए गए गोटो का उल्लेख नहीं किया है। जब पृथ्वी युवा थी तब मूल संख्याओं की संख्या थी। आप निम्नलिखित लिख सकते हैं: 100 एन = ए * 100; गोटो एन। डिबगिंग की कोशिश करें कि :)
22

7
@ JohnR.Strohm मैंने दीजकस्ट्रा का पेपर पढ़ा है। यह 1968 में लिखा गया था और सुझाव देता है कि गोटो की आवश्यकता उन भाषाओं में कम हो सकती है जिनमें स्विच स्टेटमेंट और फ़ंक्शंस जैसी उन्नत सुविधाएँ शामिल हैं। यह उन भाषाओं के जवाब में लिखा गया था जिसमें गोटो प्रवाह नियंत्रण की प्राथमिक विधि थी, और कार्यक्रम में किसी भी बिंदु पर कूदने के लिए इसका इस्तेमाल किया जा सकता था। जबकि इस पत्र के बाद विकसित की गई भाषाओं में, उदाहरण के लिए C, गोटो केवल एक ही स्टैक फ्रेम में स्थानों पर कूद सकते हैं, और आमतौर पर केवल तब उपयोग किया जाता है जब अन्य विकल्प अच्छी तरह से काम नहीं करते हैं। (जारी ...)
रे

10
(... जारी रखा) उस समय उनके अंक वैध थे, लेकिन अब प्रासंगिक नहीं हैं, भले ही गोटो एक अच्छा विचार है या नहीं। अगर हम यह तर्क देना चाहते हैं कि एक या दूसरे तरीके, तर्क दिए जाने चाहिए जो आधुनिक भाषाओं से संबंधित हैं। वैसे, क्या आपने नुथ के "गोटो स्टेटमेंट्स के साथ स्ट्रक्चर्ड प्रोग्रामिंग" पढ़ा है?
रे

जवाबों:


2

यहाँ यह देखने का एक तरीका है जो मैंने अभी तक अन्य उत्तरों में नहीं देखा है।

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

एक गोटो प्रभावी रूप से पूरे कार्यक्रम के लिए आपके तर्क का दायरा बढ़ाता है। यह केवल कुछ पंक्तियों में फैले किसी भी छोटे कार्यक्रम के लिए आपके मस्तिष्क को हराने के लिए निश्चित है।

तो आप यह नहीं बता पाएंगे कि क्या आपने कोई गलती की है क्योंकि आपके गरीब के छोटे सिर को लेने और जांचने के लिए अभी बहुत कुछ है। यह वास्तविक समस्या है, बग केवल एक संभावित परिणाम है।


गैर-स्थानीय गोटो?
Deduplicator

thebrain.mcgill.ca/flash/capsules/experience_jaune03.html << मानव मन एक बार में औसतन 7 चीजों का हिसाब रख सकता है। आपका तर्क इस सीमा में खेलता है, क्योंकि विस्तार के दायरे में कई और चीजें शामिल होंगी जिन्हें ट्रैक करने की आवश्यकता है। इस प्रकार बग के प्रकार जो पेश किए जाएंगे, वे संभवतः चूक और विस्मृति के एक प्रकार हैं। आप सामान्य रूप से "अपने दायरे को चुस्त-दुरुस्त रखने" की एक नीच रणनीति और अच्छे अभ्यास की पेशकश करते हैं। जैसे, मैं इस जवाब को स्वीकार करता हूं। अच्छा काम मार्टिन।
अकीवा

1
कितना मजेदार था वो?! 200 से अधिक वोटों के बीच, सिर्फ 1 से जीत!
मार्टिन माट

68

ऐसा नहीं है कि यह gotoअपने आप में खराब है। (आखिरकार, कंप्यूटर में हर जंप इंस्ट्रक्शन एक गोटो है।) समस्या यह है कि प्रोग्रामिंग की एक मानवीय शैली है जो संरचित प्रोग्रामिंग को पूर्व-दिनांक करता है, जिसे "फ्लो-चार्ट" प्रोग्रामिंग कहा जा सकता है।

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

स्पेगेटी कोड के साथ समस्या यह है कि आप, प्रोग्रामर, "पता" यह सही था, लेकिन आप इसे कैसे साबित कर सकते हैं , खुद को या किसी और को? वास्तव में, यह वास्तव में एक संभावित दुर्व्यवहार हो सकता है, और आपका ज्ञान कि यह हमेशा सही होता है गलत हो सकता है।

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

बेशक, लोग अभी भी बिना स्पेगेटी कोड लिख सकते हैं goto। सामान्य विधि एक लिखना है while(...) switch( iState ){..., जहां विभिन्न मामले iStateअलग-अलग मूल्यों पर सेट होते हैं। वास्तव में, C या C ++ में ऐसा करने के लिए एक मैक्रो लिख सकता है, और इसे नाम दे सकता है GOTO, इसलिए यह कहना कि आप उपयोग नहीं कर रहे हैं gotoएक अंतर के बिना एक अंतर है।

कोड-साबित करने का एक उदाहरण अप्रतिबंधित हो सकता है goto, एक लंबे समय से पहले मैं गतिशील रूप से बदलते उपयोगकर्ता इंटरफेस के लिए उपयोगी एक नियंत्रण संरचना पर ठोकर खाई थी। मैंने इसे अंतर निष्पादन कहा । यह पूरी तरह से ट्यूरिंग-वैश्विक है, लेकिन इसकी सत्यता को प्रमाण शुद्ध संरचित प्रोग्रामिंग पर निर्भर करता है - कोई goto, return, continue, break, या अपवाद नहीं।

यहाँ छवि विवरण दर्ज करें


49
अधिकांश तुच्छ कार्यक्रमों को छोड़कर सुधार साबित नहीं किया जा सकता है , यहां तक ​​कि जब संरचित प्रोग्रामिंग का उपयोग उन्हें लिखने के लिए किया जाता है। आप केवल अपने आत्मविश्वास का स्तर बढ़ा सकते हैं; संरचित प्रोग्रामिंग वह पूरा करती है।
राबर्ट हार्वे

23
@MikeDunlavey: संबंधित: "उपरोक्त कोड में बग से सावधान रहें; मैंने केवल इसे सही साबित किया है, इसे नहीं।" Staff.fnwi.uva.nl/p.vanemdeboas/knuthnote.pdf
डक

26
@ रोबर्टहवे यह बिल्कुल सच नहीं है कि शुद्धता प्रमाण केवल तुच्छ कार्यक्रमों के लिए व्यावहारिक हैं। हालांकि, संरचित प्रोग्रामिंग की तुलना में अधिक विशिष्ट उपकरण आवश्यक हैं।
माइक हास्केल

18
@ मालिक: यह एक शोध परियोजना है। इस तरह की शोध परियोजना का लक्ष्य यह दिखाना है कि वे एक सत्यापित संकलक लिख सकते हैं यदि उनके पास संसाधन हैं। यदि आप उनके वर्तमान कार्य को देखते हैं, तो आप देखेंगे कि वे केवल सी के बाद के संस्करणों का समर्थन करने में रुचि नहीं रखते हैं, बल्कि वे सही गुणों का विस्तार करने में रुचि रखते हैं जो वे साबित कर सकते हैं। और इसके लिए, यह पूरी तरह से अप्रासंगिक है कि क्या वे C90, C99, C11, पास्कल, फोरट्रान, अल्गोल, या प्लांकालुकल का समर्थन करते हैं।
जोग डब्ल्यू डब्ल्यू मित्तग

8
@martineau: मैं उन "बोसॉन वाक्यांशों" की लीरी हूं, जहां प्रोग्रामर लाइन में गिरावट की तरह यह मानते हुए सहमत हैं कि यह बुरा या अच्छा है, क्योंकि अगर वे नहीं करते हैं तो वे बैठ जाएंगे। चीजों के लिए अधिक बुनियादी कारण होना चाहिए।
माइक डनलैवी

63

गोटो क्यों खतरनाक है?

  • gotoअपने आप अस्थिरता पैदा नहीं करता है। लगभग 100,000 gotoएस के बावजूद , लिनक्स कर्नेल अभी भी स्थिरता का एक मॉडल है।
  • gotoअपने आप में सुरक्षा कमजोरियों का कारण नहीं होना चाहिए। हालाँकि कुछ भाषाओं में, इसे try/ catchअपवाद प्रबंधन ब्लॉकों के साथ मिलाने से इस CERT अनुशंसा में बताई गई कमजोरियाँ हो सकती हैं । मुख्यधारा सी ++ संकलक ध्वज और ऐसी त्रुटियों को रोकती है, लेकिन दुर्भाग्य से, पुराने या अधिक विदेशी संकलक नहीं हैं।
  • gotoअपठनीय और अचूक कोड का कारण बनता है। इसे स्पेगेटी कोड भी कहा जाता है , क्योंकि स्पैगेटी प्लेट की तरह, नियंत्रण के प्रवाह का पालन करना बहुत मुश्किल होता है जब बहुत अधिक गोटो हो।

यहां तक ​​कि अगर आप स्पेगेटी कोड से बचने का प्रबंधन करते हैं और यदि आप केवल कुछ गोटो का उपयोग करते हैं, तो वे अभी भी बग और रिसोर्स लीकिंग की सुविधा देते हैं:

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

अतिरिक्त जानकारी और उद्धरण:

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

  • जेम्स गोसलिंग और हेनरी मैकगिल्टन ने 1995 के जावा भाषा के पर्यावरण श्वेत पत्र में लिखा है :

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

  • Bjarne Stroustrup इन आकर्षक शब्दों में अपनी शब्दावली में गोटो को परिभाषित करता है :

    गोटो - कुख्यात गोटो। मशीन में मुख्य रूप से उपयोगी C ++ कोड उत्पन्न होता है।

गोटो का उपयोग कब किया जा सकता है?

K & R की तरह मैं गोटो को लेकर हठधर्मिता नहीं कर रहा हूं। मैं स्वीकार करता हूं कि ऐसी परिस्थितियां हैं जहां गोटो से किसी का जीवन आसान हो सकता है।

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

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

गोटो का उपयोग भाषा पर बहुत अधिक निर्भर करता है:

  • C ++ में, RAII के उचित उपयोग से कंपाइलर उन वस्तुओं को स्वचालित रूप से नष्ट कर देता है जो दायरे से बाहर जाती हैं, ताकि संसाधनों / लॉक को वैसे भी साफ किया जा सके, और गोटो की कोई वास्तविक आवश्यकता नहीं होगी।

  • जावा में (ऊपर जावा के लेखक उद्धरण और यह देखने के लिए गोटो कोई आवश्यकता नहीं है उत्कृष्ट स्टैक ओवरफ़्लो जवाब ): कचरा कलेक्टर साफ है कि गंदगी, break, continue, और try/ catchअपवाद हैंडलिंग सभी मामले में जहां कवर gotoसहायक हो सकता है, लेकिन में एक सुरक्षित और बेहतर तौर तरीका। जावा की लोकप्रियता यह साबित करती है कि आधुनिक भाषा में गोटो के बयान से बचा जा सकता है।

प्रसिद्ध SSL गोटो पर ज़ूम करना भेद्यता को विफल करता है

महत्वपूर्ण अस्वीकरण: टिप्पणियों में उग्र चर्चा के मद्देनजर, मैं स्पष्ट करना चाहता हूं कि मैं इस बात का ढोंग नहीं करता हूं कि गोटो का बयान ही इस बग का कारण है। मैं इस बात का ढोंग नहीं करता कि बिना गोटे के बग नहीं होगा। मैं केवल यह दिखाना चाहता हूं कि एक गोटो एक गंभीर बग में शामिल हो सकता है।

मुझे नहीं पता कि gotoप्रोग्रामिंग के इतिहास में कितने गंभीर कीड़े हैं : विवरणों का अक्सर संचार नहीं किया जाता है। हालाँकि एक प्रसिद्ध Apple SSL बग था जिसने iOS की सुरक्षा को कमजोर कर दिया था। इस बग के कारण gotoबयान गलत कथन था।

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

एकमात्र उद्देश्य तथ्य यह है कि एक डुप्लिकेट gotoको समय से पहले फ़ंक्शन से बाहर निकलने के लिए प्रेरित किया गया था। कोड को देखते हुए, केवल अन्य एकल कथन जो एक ही प्रभाव का कारण हो सकता था, एक वापसी होगी।

इस फ़ाइलSSLEncodeSignedServerKeyExchange() में त्रुटि है :

    if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0)
        goto fail;
    if ((err =...) !=0)
        goto fail;
    if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
        goto fail;
        goto fail;  // <====OUCH: INDENTATION MISLEADS: THIS IS UNCONDITIONDAL!!
    if (...)
        goto fail;

    ... // Do some cryptographic operations here

fail:
    ... // Free resources to process error

सशर्त ब्लॉक के चारों ओर घुंघराले ब्रेसिज़ बग को रोक सकते थे:
यह या तो संकलन (और इसलिए सुधार) या एक अनावश्यक हानिरहित गोटो में एक वाक्यविन्यास त्रुटि के लिए नेतृत्व करेगा। वैसे, जीसीसी 6 असंगत इंडेंटेशन का पता लगाने के लिए अपनी वैकल्पिक चेतावनी के कारण इन त्रुटियों को हाजिर करने में सक्षम होगा।

लेकिन पहले स्थान पर, इन सभी गोटो को अधिक संरचित कोड के साथ टाला जा सकता था। तो गोटो कम से कम अप्रत्यक्ष रूप से इस बग का एक कारण है। कम से कम दो अलग-अलग तरीके हैं जो इसे टाल सकते थे:

दृष्टिकोण 1: यदि खंड या नेस्टेड ifएस

क्रमिक रूप से त्रुटि के लिए बहुत सारी शर्तों का परीक्षण करने के बजाय, और हर बार failसमस्या के मामले में एक लेबल पर भेजने के बाद , कोई व्यक्ति क्रिप्टोग्राफिक संचालन को अंजाम देने के लिए चुन सकता है, जो ifकेवल तभी होगा जब कोई गलत पूर्व शर्त नहीं थी:

    if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) == 0 &&
        (err = ...) == 0 ) &&
        (err = ReadyHash(&SSLHashSHA1, &hashCtx)) == 0) &&
        ...
        (err = ...) == 0 ) )
    {
         ... // Do some cryptographic operations here
    }
    ... // Free resources

दृष्टिकोण 2: एक त्रुटि संचायक का उपयोग करें

यह दृष्टिकोण इस तथ्य पर आधारित है कि यहां लगभग सभी कथन errत्रुटि कोड सेट करने के लिए कुछ फ़ंक्शन को कॉल करते हैं , और शेष कोड को केवल err0 (यानी, त्रुटि के बिना निष्पादित फ़ंक्शन) निष्पादित करते हैं। एक अच्छा सुरक्षित और पठनीय विकल्प है:

bool ok = true;
ok =  ok && (err = ReadyHash(&SSLHashSHA1, &hashCtx))) == 0;
ok =  ok && (err = NextFunction(...)) == 0;
...
ok =  ok && (err = ...) == 0;
... // Free resources

यहां, एक भी गोटो नहीं है: विफलता से बाहर निकलने के लिए जल्दी से कूदने का कोई जोखिम नहीं है। और नेत्रहीन रूप से एक गलत लाइन या भूल जाना आसान होगा ok &&

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

आप फ़ंक्शन के अंत में एक निरंतरता जांच की परिकल्पना भी कर सकते हैं जो परीक्षण चरण के दौरान ठीक ध्वज और त्रुटि कोड के बीच बेमेल पहचान कर सकता है।

assert( (ok==false && err!=0) || (ok==true && err==0) );

इस तरह की गलतियों को ==0अनजाने में !=0या तार्किक संबंधक त्रुटियों के साथ बदल दिया जाता है जिसे डिबगिंग चरण के दौरान आसानी से देखा जा सकता है।

जैसा कि कहा गया: मैं इस बात का ढोंग नहीं करता कि वैकल्पिक निर्माण किसी भी बग से बचते थे। मैं केवल यह कहना चाहता हूं कि वे बग को और अधिक कठिन बना सकते थे।


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

47
Apple "गोटो फेल" बग को सीधे कोड की एक पंक्ति के कारण डुप्लिकेट किया गया था। उस बग का विशेष प्रभाव उस लाइन के gotoब्रेस-लेस ifस्टेटमेंट के अंदर होने के कारण हुआ । लेकिन अगर आप सुझाव दे रहे हैं कि टाल- gotoमटोल की गई लाइनों के प्रभावों से आपका कोड प्रतिरक्षा बनाएगा, तो मेरे लिए आपके लिए बुरी खबर है।
ओबिस

12
आप साइड-इफ़ेक्ट के माध्यम से स्टेटमेंट निष्पादित करने के लिए शॉर्टकट बूलियन ऑपरेटर व्यवहार का उपयोग कर रहे हैं और दावा कर रहे हैं कि एक ifस्टेटमेंट की तुलना में अधिक स्पष्ट है ? मनोरंजन समय। :)
क्रेग

38
यदि "गोटो फेल" के बजाय "विफल = सत्य" कथन होता तो ठीक यही बात होती।
gnasher729

15
यह बग एक मैला डेवलपर के कारण था जो वह या वह क्या कर रहा था पर ध्यान नहीं दे रहा था, और अपने स्वयं के कोड परिवर्तनों को नहीं पढ़ रहा था । न कुछ ज्यादा, न कुछ कम। ठीक है, शायद वहाँ भी कुछ परीक्षण निरीक्षण में फेंक देते हैं।
ऑर्बिट

34

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

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

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

और हां, आपके पास एक फ़ंक्शन के अंदर कई रिटर्न स्टेटमेंट हो सकते हैं; वहाँ अभी भी हमेशा एक उचित कार्य में एक जगह है जहाँ से आप (मूल रूप से फ़ंक्शन के पीछे की ओर) लौटते हैं। यह ठीक से लौटने का मौका है इससे पहले कि एक गोटो के साथ एक समारोह से बाहर कूद के रूप में एक ही बात नहीं है।

यहाँ छवि विवरण दर्ज करें

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

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


2
टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
maple_shaft

11

"गोटो" बयान किस तरह के बग की ओर जाता है? क्या कोई ऐतिहासिक महत्वपूर्ण उदाहरण हैं?

मैं gotoबतौर एक बच्चे के रूप में BASIC प्रोग्राम लिखते समय स्टेटमेंट्स का इस्तेमाल करता था जबकि लूप्स (कमोडोर 64 BASIC के पास नहीं था जबकि-लूप्स नहीं था, और मैं फॉर-लूप्स के उचित सिंटैक्स और यूज़ को सीखने के लिए बहुत अपरिपक्व था। )। मेरा कोड अक्सर तुच्छ था, लेकिन किसी भी लूप कीड़े को गोटो के मेरे उपयोग के लिए तुरंत जिम्मेदार ठहराया जा सकता है।

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

१ ९ ६ did में जब एग्जर्स डिक्जस्ट्रा ने "गोटो को हानिकारक माना" घोषित किया, तो उन्होंने एक मुट्ठी भर उदाहरण नहीं दिए जहां संबंधित कीड़े को गोटो पर दोषी ठहराया जा सकता है, बल्कि, उन्होंने घोषित किया कि उच्च स्तर की भाषाओं के लिए अनावश्यकgoto था और इसे किस पक्ष में रखा जाना चाहिए आज हम सामान्य नियंत्रण प्रवाह पर विचार करते हैं: लूप और सशर्त। उसके शब्दों:

गो के बेलगाम उपयोग का एक तात्कालिक परिणाम यह होता है कि निर्देशांक का एक सार्थक सेट खोजना बहुत कठिन हो जाता है जिसमें प्रक्रिया की प्रगति का वर्णन करना है।
[...] करने के लिए जाने के बयान के रूप में यह खड़ा है अभी भी आदिम है, यह किसी के कार्यक्रम में गड़बड़ी करने का निमंत्रण है।

संभवत: उसके पास हर बार कोड के डिबग करने के उदाहरणों के पहाड़ थे goto। लेकिन उनका पेपर एक सामान्यीकृत स्थिति विवरण gotoथा जो प्रमाण द्वारा समर्थित था जो उच्च स्तरीय भाषाओं के लिए अनावश्यक था। सामान्यीकृत बग यह है कि आपके पास प्रश्न के तहत कोड का विश्लेषण करने की क्षमता नहीं है।

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

एक Apocryphal उदाहरण

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

एक काउंटर-उदाहरण

हालांकि, सीपीथॉन (सबसे सामान्य और संदर्भ पायथन कार्यान्वयन) का सी स्रोत gotoमहान प्रभाव के लिए बयानों का उपयोग करता है। वे कार्यों के अंत तक पहुंचने के लिए कार्यों के अंदर अप्रासंगिक नियंत्रण प्रवाह को बायपास करने के लिए उपयोग किया जाता है, जिससे कार्यों को पठनीयता खोए बिना अधिक कुशल बना दिया जाता है। यह संरचित प्रोग्रामिंग के आदर्शों में से एक का सम्मान करता है - कार्यों के लिए एक निकास बिंदु है।

रिकॉर्ड के लिए, मुझे यह काउंटर-उदाहरण सांख्यिकीय रूप से विश्लेषण करने में काफी आसान लगता है।


5
"स्टोरी ऑफ़ मेल" जो मुझे मिला है वह एक अजीब वास्तुकला पर था जहां (1) प्रत्येक मशीन भाषा निर्देश अपने ऑपरेशन के बाद एक गोटो करता है, और (2) लगातार स्मृति स्थानों में निर्देशों का क्रम लगाने के लिए यह बहुत अक्षम था। और कार्यक्रम हाथ से अनुकूलित विधानसभा में लिखा गया था, न कि संकलित भाषा।

@ माइल्सराउट मुझे लगता है कि आप यहां सही हो सकते हैं, लेकिन संरचित प्रोग्रामिंग पर विकिपीडिया पृष्ठ कहता है: "कई भाषाओं में पाया जाने वाला सबसे सामान्य विचलन, एक सबरूटीन से जल्दी बाहर निकलने के लिए वापसी विवरण का उपयोग है। इसके परिणामस्वरूप कई निकास बिंदु होते हैं। इसके बजाय संरचित प्रोग्रामिंग द्वारा आवश्यक एकल निकास बिंदु के बजाय। " - आप कह रहे हैं यह गलत है? क्या आपके पास हवाले करने का स्रोत है?
एरॉन हॉल

@AaronHall इसका मूल अर्थ नहीं है।
मील्स राउत

11

जब विगवाम वर्तमान स्थापत्य कला थी, तो उनके निर्माता निस्संदेह आपको विगवाम्स के निर्माण के बारे में व्यावहारिक सलाह दे सकते थे, कैसे धूम्रपान से बच सकते हैं, और इसी तरह। सौभाग्य से, आज के बिल्डर्स शायद उस सलाह को भूल सकते हैं।

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

जब छिद्रित कार्ड चालू प्रोग्रामिंग कला थे, तो उनके चिकित्सक आपको कार्ड के संगठन के बारे में व्यावहारिक सलाह दे सकते हैं, कैसे बयान दे सकते हैं, और इसी तरह। मुझे यकीन नहीं है कि आज वह सलाह बहुत प्रासंगिक है।

क्या आप "कथन संख्या के लिए" वाक्यांश जानने के लिए पर्याप्त पुराने हैं ? आपको इसे जानने की आवश्यकता नहीं है, लेकिन यदि आप नहीं करते हैं, तो आप उस ऐतिहासिक संदर्भ से परिचित नहीं हैं जिसमें चेतावनी gotoमुख्यतः प्रासंगिक थी।

के खिलाफ चेतावनी gotoआज बहुत प्रासंगिक नहीं है। लूप और फ़ंक्शन कॉल में / के लिए बुनियादी प्रशिक्षण के साथ, आप बहुत बार जारी करने के बारे में भी नहीं सोचेंगेgoto । जब आप इसके बारे में सोचते हैं, तो आपके पास शायद एक कारण होता है, इसलिए आगे बढ़ें।

लेकिन क्या gotoबयान का दुरुपयोग नहीं किया जा सकता है?

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

आप हाल की डरावनी कहानियों की कमी देख सकते हैं जिसमें gotoखलनायक की भूमिका है। इनमें से अधिकांश या सभी कहानियाँ 30 या 40 साल पुरानी लगती हैं। यदि आप उन कहानियों को ज्यादातर अप्रचलित मानते हैं, तो आप ठोस आधार पर खड़े होते हैं।


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

1
आपकी पोस्ट बहुत अच्छी है मैं टिप्पणियों को गलत नहीं कह सकता।
Pieter B

7

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


1
विजुअल बेसिक 6 और VBA दर्दनाक त्रुटि हैंडलिंग है, लेकिन अगर आप का उपयोग करें On Error Goto errh, तो आप उपयोग कर सकते हैं Resumeफिर से प्रयास करना, Resume Nextहमलावर लाइन को छोड़, और Erlपता करने के लिए जो लाइन में था (यदि आप लाइन नंबर का उपयोग करें)।
सेस टिम्मरमैन

@CeesTimmerman मैंने Visual Basic के साथ बहुत कम किया है, मुझे नहीं पता था। मैं इसके बारे में एक टिप्पणी जोड़ूंगा।
qfwfq

2
@CeesTimmerman: "रिज्यूमे" का VB6 शब्दार्थ भयानक होता है यदि कोई सबरूटीन में कोई त्रुटि होती है जिसका स्वयं का त्रुटि ब्लॉक नहीं होता है। Resumeशुरू से उस फ़ंक्शन को फिर से निष्पादित Resume Nextकरेगा , और फ़ंक्शन में सब कुछ छोड़ देगा जो अभी तक नहीं है।
सुपरकैट

2
@supercat जैसा मैंने कहा, यह दर्दनाक है। यदि आपको सटीक लाइन जानने की आवश्यकता है, तो आपको उन सभी को नंबर देना चाहिए, या On Error Goto 0मैन्युअल रूप से डिबग के साथ त्रुटि से निपटने को अस्थायी रूप से अक्षम करना चाहिए । Resumeका उपयोग जाँच के बाद Err.Numberऔर आवश्यक समायोजन करने के लिए किया जाता है ।
सेस टिम्मरमैन

1
मुझे ध्यान देना चाहिए कि एक आधुनिक भाषा में, gotoकेवल लेबल वाली लाइनों के साथ काम करता है, जो कि लेबल वाले छोरों द्वारा छितराया हुआ प्रतीत होता है ।
सेस टिम्मरमैन

7

गोटो अन्य प्रकार के प्रवाह नियंत्रण की तुलना में मनुष्यों के लिए कठिन है।

सही कोड प्रोग्रामिंग कठिन है। सही प्रोग्राम लिखना कठिन है, यह निर्धारित करना कि प्रोग्राम सही हैं या नहीं, प्रोग्राम को सही साबित करना कठिन है।

प्रोग्रामिंग के बारे में बाकी सब चीज़ों की तुलना में आसानी से आप जो चाहते हैं, उसके लिए कोड प्राप्त करना।

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

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

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

कॉटआउट समर्थन के बिना भाषाओं में "उथला" कोरटाइन (जैसे सी ++ प्री-सी ++ 20 और सी) गोटो और मैनुअल स्टेट मैनेजमेंट के मिश्रण का उपयोग करना संभव है। "डीप" कोरआउट को C के कार्यों setjmpऔर longjmpकार्यों का उपयोग करके किया जा सकता है ।

ऐसे मामले हैं जहां कॉरटॉयन्स इतने उपयोगी हैं कि उन्हें मैन्युअल रूप से लिखना और ध्यान से इसके लायक है।

C ++ के मामले में, उन्हें पर्याप्त उपयोगी पाया जा रहा है कि वे उनका समर्थन करने के लिए भाषा का विस्तार कर रहे हैं। gotoऔर मैनुअल राज्य प्रबंधन एक शून्य लागत अमूर्त परत के पीछे छिपा हुआ जा रहा है, उन्हें लिखने के लिए प्रोग्रामर की अनुमति के बिना गोटो, के अपने गंदगी साबित करने के लिए होने की कठिनाई void**है, मैनुअल निर्माण / राज्य का विनाश, आदि सही है।

गोटो एक उच्च स्तर अमूर्त के पीछे छिपा हुआ हो जाता है, की तरह whileया forया ifया switch। उन उच्च स्तर के अमूर्त सही साबित करने और जांचने में आसान होते हैं।

यदि भाषा उनमें से कुछ को याद कर रही थी (जैसे कुछ आधुनिक भाषाएं कोरआउट्स याद कर रही हैं), या तो एक पैटर्न के साथ सीमित करना जो समस्या को फिट नहीं करता है, या गोटो का उपयोग करना, आपके विकल्प बन जाते हैं।

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


1
longjmpsetjmpएक पैरेंट फंक्शन में स्टैक को वापस लाने के लिए C में केवल कानूनी है । (घोंसले के कई स्तरों से बाहर निकलने की तरह, लेकिन लूप के बजाय फ़ंक्शन कॉल के लिए)। एक फ़ंक्शन longjjmpसे setjmpकिए गए संदर्भ के संदर्भ में, जो लौटा है, कानूनी नहीं है (और मुझे संदेह है कि ज्यादातर मामलों में अभ्यास में काम नहीं करेगा)। मैं सह-दिनचर्या से परिचित नहीं हूं, लेकिन उपयोगकर्ता-थ्रेड के समान सह-दिनचर्या के आपके विवरण से, मुझे लगता है कि इसे अपने स्वयं के स्टैक के साथ-साथ एक सहेजे गए-रजिस्टर संदर्भ की आवश्यकता होगी, और longjmpकेवल आपको रजिस्टर करना होगा -सावन, एक अलग ढेर नहीं।
पीटर कॉर्ड्स

1
ओह, मुझे सिर्फ गुगली करनी चाहिए: fanf.livejournal.com/105413.html कोरटाइन चलाने के लिए स्टैक स्पेस बनाने का वर्णन करता है। (जिस पर मुझे संदेह था, बस सेटजम्प / लॉन्गजम्प का उपयोग करने के लिए आवश्यक है)।
पीटर कॉर्ड्स

2
@PeterCordes: कार्यान्वयन के लिए किसी भी साधन को प्रदान करने की आवश्यकता नहीं होती है जिसके द्वारा कोड एक जोड़ी jmp_buff बना सकता है जो कि एक coroutine के रूप में उपयोग के लिए उपयुक्त है। कुछ कार्यान्वयन एक साधन निर्दिष्ट करते हैं जिसके माध्यम से कोड एक बना सकता है, भले ही मानक को ऐसी क्षमता प्रदान करने की आवश्यकता न हो। मैं कोड का वर्णन नहीं करूंगा जो "मानक सी" जैसी तकनीकों पर निर्भर करता है, क्योंकि कई मामलों में एक jmp_buff एक अपारदर्शी संरचना होगी जो विभिन्न संकलक के बीच लगातार व्यवहार करने की गारंटी नहीं है।
सुपरकैट

6

इस कोड पर एक नज़र डालें, http://www-personal.umich.edu/~axe/research/Software/CC/CC2/TourExec1.1.f.html से, जो वास्तव में एक बड़े कैदी के दिलनमा सिमुलेशन का हिस्सा था। यदि आपने पुराना FORTRAN या BASIC कोड देखा है, तो आपको एहसास होगा कि यह असामान्य नहीं है।

C  Not nice rules in second round of tour (cut and pasted 7/15/93)
   FUNCTION K75R(J,M,K,L,R,JA)
C  BY P D HARRINGTON
C  TYPED BY JM 3/20/79
   DIMENSION HIST(4,2),ROW(4),COL(2),ID(2)
   K75R=JA       ! Added 7/32/93 to report own old value
   IF (M .EQ. 2) GOTO 25
   IF (M .GT. 1) GOTO 10
   DO 5 IA = 1,4
     DO 5 IB = 1,2
5  HIST(IA,IB) = 0

   IBURN = 0
   ID(1) = 0
   ID(2) = 0
   IDEF = 0
   ITWIN = 0
   ISTRNG = 0
   ICOOP = 0
   ITRY = 0
   IRDCHK = 0
   IRAND = 0
   IPARTY = 1
   IND = 0
   MY = 0
   INDEF = 5
   IOPP = 0
   PROB = .2
   K75R = 0
   RETURN

10 IF (IRAND .EQ. 1) GOTO 70
   IOPP = IOPP + J
   HIST(IND,J+1) = HIST(IND,J+1) + 1
   IF (M .EQ. 15 .OR. MOD(M,15) .NE. 0 .OR. IRAND .EQ. 2) GOTO 25
   IF (HIST(1,1) / (M - 2) .GE. .8) GOTO 25
   IF (IOPP * 4 .LT. M - 2 .OR. IOPP * 4 .GT. 3 * M - 6) GOTO 25
   DO 12 IA = 1,4
12 ROW(IA) = HIST(IA,1) + HIST(IA,2)

   DO 14 IB = 1,2
     SUM = .0
     DO 13 IA = 1,4
13   SUM = SUM + HIST(IA,IB)
14 COL(IB) = SUM

   SUM = .0
   DO 16 IA = 1,4
     DO 16 IB = 1,2
       EX = ROW(IA) * COL(IB) / (M - 2)
       IF (EX .LE. 1.) GOTO 16
       SUM = SUM + ((HIST(IA,IB) - EX) ** 2) / EX
16 CONTINUE

   IF (SUM .GT. 3) GOTO 25
   IRAND = 1
   K75R = 1
   RETURN

25 IF (ITRY .EQ. 1 .AND. J .EQ. 1) IBURN = 1
   IF (M .LE. 37 .AND. J .EQ. 0) ITWIN = ITWIN + 1
   IF (M .EQ. 38 .AND. J .EQ. 1) ITWIN = ITWIN + 1
   IF (M .GE. 39 .AND. ITWIN .EQ. 37 .AND. J .EQ. 1) ITWIN = 0
   IF (ITWIN .EQ. 37) GOTO 80
   IDEF = IDEF * J + J
   IF (IDEF .GE. 20) GOTO 90
   IPARTY = 3 - IPARTY
   ID(IPARTY) = ID(IPARTY) * J + J
   IF (ID(IPARTY) .GE. INDEF) GOTO 78
   IF (ICOOP .GE. 1) GOTO 80
   IF (M .LT. 37 .OR. IBURN .EQ. 1) GOTO 34
   IF (M .EQ. 37) GOTO 32
   IF (R .GT. PROB) GOTO 34
32 ITRY = 2
   ICOOP = 2
   PROB = PROB + .05
   GOTO 92

34 IF (J .EQ. 0) GOTO 80
   GOTO 90

70 IRDCHK = IRDCHK + J * 4 - 3
   IF (IRDCHK .GE. 11) GOTO 75
   K75R = 1
   RETURN

75 IRAND = 2
   ICOOP = 2
   K75R = 0
   RETURN

78 ID(IPARTY) = 0
   ISTRNG = ISTRNG + 1
   IF (ISTRNG .EQ. 8) INDEF = 3
80 K75R = 0
   ITRY = ITRY - 1
   ICOOP = ICOOP - 1
   GOTO 95

90 ID(IPARTY) = ID(IPARTY) + 1
92 K75R = 1
95 IND = 2 * MY + J + 1
   MY = K75R
   RETURN
   END

यहाँ बहुत सारे मुद्दे हैं जो यहाँ GOTO के बयान से परे हैं; मुझे ईमानदारी से लगता है कि गोटो का बयान एक बलि का बकरा था। लेकिन नियंत्रण प्रवाह यहां बिल्कुल स्पष्ट नहीं है, और कोड को उन तरीकों से एक साथ मिलाया जाता है जो यह स्पष्ट करते हैं कि क्या चल रहा है। यहां तक ​​कि टिप्पणियों को जोड़ने या बेहतर चर नामों का उपयोग किए बिना, इसे बिना GOTO के ब्लॉक संरचना में बदलने से पढ़ने और अनुसरण करने में बहुत आसानी होगी।


4
यह सच है :-) उल्लेख के लायक हो सकता है: विरासत FORTAN और BASIC में ब्लॉक संरचनाएं नहीं थीं, ताकि यदि कोई THEN खंड एक पंक्ति में पकड़ न सके, तो GOTO एकमात्र विकल्प था।
क्रिस्टोफ़

संख्याओं के बजाय पाठ लेबल, या गिने पंक्तियों पर कम से कम टिप्पणी से बहुत मदद मिलेगी।
सेस टिम्मरमैन

मेरे फोरट्रान-IV दिनों में वापस: मैंने IF / ELSE IF / ELSE ब्लॉक, WHILE लूप और BREAK और NEXT को लूप में लागू करने के लिए GOTO के मेरे उपयोग को प्रतिबंधित कर दिया। किसी ने मुझे स्पेगेटी कोड की बुराइयों को दिखाया और आपको इससे बचने के लिए संरचना क्यों करनी चाहिए, भले ही आपको अपने ब्लॉक संरचनाओं को गोटो के साथ लागू करना पड़े। बाद में मैंने प्री-प्रोसेसर (RATFOR, IIRC) का उपयोग शुरू कर दिया। गोटो आंतरिक रूप से बुराई नहीं है, यह सिर्फ एक अति-शक्तिशाली निम्न-स्तर का निर्माण है जो नक्शे को एक कोडांतरक शाखा निर्देश के लिए बनाता है। यदि आपको इसका उपयोग करना है क्योंकि आपकी भाषा की कमी है, तो इसका उपयोग उचित ब्लॉक संरचनाओं को बनाने या बढ़ाने के लिए करें।
nigel222

@CeesTimmerman: यह उद्यान-किस्म FORTRAN IV कोड है। फोरट्रान IV में पाठ लेबल समर्थित नहीं थे। मुझे नहीं पता कि भाषा के अधिक हाल के संस्करण उनका समर्थन करते हैं या नहीं। कोड के रूप में एक ही लाइन पर टिप्पणियाँ मानक फोरट्रान IV में समर्थित नहीं थीं, हालांकि उनका समर्थन करने के लिए विक्रेता-विशिष्ट एक्सटेंशन हो सकते हैं। मुझे नहीं पता कि "वर्तमान" फोरट्रान मानक क्या कहता है: मैंने बहुत समय पहले फोरट्रान को छोड़ दिया था, और मुझे यह याद नहीं है। (सबसे हालिया FORTRAN कोड मैंने 1970 के दशक के शुरू में PASCAL के लिए एक मजबूत समानता के रूप में देखा है।)
बजे जॉन आर। स्ट्रोम

1
@CeesTimmerman: विक्रेता-विशिष्ट एक्सटेंशन। सामान्य रूप से कोड टिप्पणियों पर वास्तव में शर्मीली है। इसके अलावा, एक सम्मेलन है जो कुछ स्थानों पर सामान्य हो गया है, केवल लाइन नंबर को केवल CONTINUE और FORMAT कथनों पर रखना, जिससे बाद में लाइनें जोड़ना आसान हो सके। यह कोड उस सम्मेलन का पालन नहीं करता है।
जॉन आर। स्ट्रॉहम

0

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

कोड की एक एकल इकाई के भीतर, एक ही सिद्धांत लागू होता है। यदि आप लगातार संरचित प्रोग्रामिंग या ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग सिद्धांतों को लागू करते हैं, तो आप नहीं करेंगे:

  1. कोड के माध्यम से अप्रत्याशित पथ बनाएं
  2. अपरिभाषित या अभेद्य चर मूल्यों के साथ कोड के वर्गों में पहुंचें
  3. अपरिभाषित या अभेद्य चर मूल्यों के साथ कोड के एक पथ से बाहर निकलें
  4. एक लेनदेन इकाई को पूरा करने में विफल
  5. स्मृति में कोड या डेटा के कुछ हिस्सों को छोड़ दें जो प्रभावी रूप से मृत हैं, लेकिन कचरा सफाई और पुनः प्राप्ति के लिए अयोग्य हैं, क्योंकि आपने एक स्पष्ट निर्माण का उपयोग करके उनकी रिहाई का संकेत नहीं दिया है जो कोड नियंत्रण पथ के रूप में उन्हें जारी करने वाले यूनिट से बाहर निकलता है

इन प्रोसेसिंग त्रुटियों के कुछ और सामान्य लक्षणों में मेमोरी लीक, मेमोरी होर्डिंग, पॉइंटर ओवरफ्लो, क्रैश, अपूर्ण डेटा रिकॉर्ड, रिकॉर्ड ऐड / chg / डिलीट अपवाद, मेमोरी पेज दोष, और इसी तरह शामिल हैं।

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


3
आपने gotoएक बार भी उल्लेख किए बिना उत्तर दिया । :)
रॉबर्ट हार्वे

0

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


गोटो का उपयोग करने / न करने के कारण :

  • यदि आपको एक लूप की आवश्यकता है, तो आपको उपयोग करना होगा whileया for

  • यदि आपको सशर्त कूदने की आवश्यकता है, तो उपयोग करें if/then/else

  • यदि आपको प्रक्रिया की आवश्यकता है, तो फ़ंक्शन / विधि को कॉल करें।

  • यदि आपको कोई फ़ंक्शन छोड़ने की आवश्यकता है, तो बस return

मैं अपनी उंगलियों के स्थानों पर भरोसा कर सकता हूं, जहां मैंने देखा gotoहै और ठीक से उपयोग किया है।

  • CPython
  • libKTX
  • शायद कुछ और

LibKTX में एक फ़ंक्शन होता है जिसमें निम्नलिखित कोड होते हैं

if(something)
    goto cleanup;

if(bla)
    goto cleanup;

cleanup:
    delete [] array;

अब इस जगह gotoमें उपयोगी है क्योंकि भाषा C है:

  • हम एक फंक्शन के अंदर हैं
  • हम एक सफाई फ़ंक्शन नहीं लिख सकते (क्योंकि हम एक और गुंजाइश दर्ज करते हैं, और सुलभ कॉलर फ़ंक्शन स्थिति अधिक बोझ है)

यह उपयोग मामला उपयोगी है क्योंकि C में हमारे पास कक्षाएं नहीं हैं, इसलिए सफाई का सबसे सरल तरीका a का उपयोग कर रहा है goto

यदि हमारे पास C ++ में समान कोड है तो अब गोटो की कोई आवश्यकता नहीं है:

class MyClass{
    public:

    void Function(){
        if(something)
            return Cleanup(); // invalid syntax in C#, but valid in C++
        if(bla)
            return Cleanup(); // invalid syntax in C#, but valid in C++
    }

    // access same members, no need to pass state (compiler do it for us).
    void Cleanup(){

    }



}

यह किस तरह के कीड़े को जन्म दे सकता है? कुछ भी। अनंत लूप, निष्पादन का गलत क्रम, ढेर पेंच ।।

एक प्रलेखित मामला एसएसएल में एक भेद्यता है जिसने मैन को गोटो के गलत उपयोग के कारण होने वाले मध्य हमलों में अनुमति दी है: यहां एक लेख है

यह एक टाइपो त्रुटि है, लेकिन कुछ समय के लिए किसी का ध्यान नहीं गया, अगर कोड को दूसरे तरीके से संरचित किया गया था, तो ठीक से परीक्षण किया गया था ऐसी त्रुटि संभव नहीं हो सकती थी।


2
एक उत्तर के लिए बहुत सारी टिप्पणियां हैं जो बहुत स्पष्ट रूप से समझाती हैं कि "गोटो" का उपयोग एसएसएल बग के लिए पूरी तरह से अपूरणीय था - बग एक कोड की एक पंक्ति के लापरवाह दोहराव के कारण होता था, इसलिए इसे एक बार सशर्त रूप से निष्पादित किया गया था, और एक बार बिना किसी शर्त के।
gnasher729

हाँ, मैं स्वीकार करने से पहले एक गोटो बग के बेहतर ऐतिहासिक उदाहरण की प्रतीक्षा कर रहा हूं। जैसा कहा गया है; इससे कोई फर्क नहीं पड़ता कि कोड की उस लाइन पर क्या था; घुंघराले ब्रेसिज़ की कमी ने इसे निष्पादित किया होगा और चाहे कोई त्रुटि हुई हो। मैं हालांकि उत्सुक हूं; "स्टैक स्क्रू" क्या है?
अक्विवा

1
कोड से एक उदाहरण मैंने पहले PL / 1 CICS में काम किया था। कार्यक्रम में सिंगल लाइन मैप्स से युक्त स्क्रीन लगाई गई है। जब स्क्रीन लौटाया गया, तो उसे उन मानचित्रों का सरणी मिला जिसे उसने भेजा था। एक सरणी में सूचकांक को खोजने के लिए उस के तत्वों का उपयोग किया, और फिर उस सूचकांक का उपयोग सरणी चर के सूचकांक में करने के लिए एक GOTO करने के लिए किया ताकि यह उस व्यक्तिगत मानचित्र को संसाधित कर सके। यदि भेजे गए मानचित्रों का सरणी गलत था (या दूषित किया गया था) तो यह गलत लेबल पर GOTO करने की कोशिश कर सकता है, या इससे भी बुरी दुर्घटना हो सकती है क्योंकि यह लेबल चर की सरणी के अंत के बाद एक तत्व तक पहुंच गया है। केस प्रकार के सिंटैक्स का उपयोग करने के लिए फिर से लिखा गया।
किकस्टार्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.