2012-01-06 16 views
8

कई महीने पहले, मुझे कुछ कोड ठीक करना पड़ा जिससे कुछ समस्याएं हुईं। कोड इस तरह मूल रूप से देखा:यह स्पष्ट अनंत रिकर्सन क्यों एक कंपाइलर चेतावनी देता है?

int badFun() { return badFun(); }

यह स्पष्ट रूप से उच्च स्तर की भाषा मैं (SilkTest में 4Test) के साथ काम कर रहा था में भी एक ढेर अतिप्रवाह का कारण बना। इस कोड को फायदेमंद के रूप में देखा जा सकता है कोई रास्ता नहीं है। स्क्रिप्ट समाप्त होने के बाद समस्याओं का पहला संकेत चेतावनी दी गई थी, लेकिन कोई संकलन त्रुटियों या चेतावनियां नहीं थीं। उत्सुकता से, मैंने सी ++, सी # और पायथन में एक ही संरचना के साथ प्रोग्राम लिखने की कोशिश की, और उनमें से सभी संकलित त्रुटियों या चेतावनियों के साथ संकलित/व्याख्या की गईं, यहां तक ​​कि सभी मामलों में रनटाइम त्रुटियां भी थीं। मैंने इनमें से किसी भी मामले में कोई चेतावनी भी नहीं देखी। डिफ़ॉल्ट रूप से यह संभावित समस्या के रूप में क्यों नहीं देखा जाता है?

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

+4

क्या आपका प्रश्न स्वयं सी #, सी ++ * या * पायथन के बारे में है? कोड नमूना मेरे लिए सी # जैसी पूरी तरह दिखता है। – BoltClock

+10

यह कुछ बेवकूफ करने से आपको रखने के लिए संकलक का काम नहीं है। अधिकांश भाषाओं में, कुछ बाहरी घटनाओं के लिए बाहर निकलने के लिए इस तरह के निर्माण का कारण बनना संभव है। –

+0

एमएसवीसी (सी ++) में, यदि आप फ़ंक्शन को कॉल करते हैं तो यह आपको चेतावनी देगा: 'चेतावनी C4717:' badFun ': सभी नियंत्रण पथों पर रिकर्सिव, फ़ंक्शन रनटाइम स्टैक ओवरफ़्लो' – Mysticial

उत्तर

39

यहां सौदा है: कंपाइलर चेतावनियां विशेषताएं हैं। सुविधाओं को प्रयास की आवश्यकता है, और प्रयास एक सीमित मात्रा है। (इसे डॉलर में मापा जा सकता है या इसे किसी ओपन सोर्स प्रोजेक्ट को देने के इच्छुक घंटों की संख्या में मापा जा सकता है, लेकिन मैं आपको आश्वस्त करता हूं, यह सीमित है।)

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

यह सभी सुविधाओं के लिए सच है। चेतावनियों में विशेष अतिरिक्त चिंताएं हैं। एक चेतावनी कोड के बारे में होना चाहिए जिसमें निम्नलिखित विशेषताएं हैं:

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

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

इस प्रकार, यह चेतावनी देने के लिए हमारे समय के लायक नहीं है। ऐसे बजट हैं जो हम बजट खर्च कर सकते हैं।

+2

+1 उत्कृष्ट उत्तर और वास्तव में जो मैं पूछ रहा था उस पर हो जाता है। मुझे पता है कि कंपाइलर्स आपको भयानक कोड लिखने से नहीं रोकते हैं, लेकिन अच्छे कंपाइलर्स को कम से कम "हे, व्हाटचा डिन डॉन" फेंकना चाहिए? कभी कभी। – joshin4colours

+2

'int BadProperty {get {return badProperty;}} 'और उसके सेटर समकक्ष के साथ संबंधित समस्या है, जहां गलती करना बहुत आसान है, और यह आसान नहीं है। लेकिन जब आप वास्तव में कोड चलाते हैं तो यह समस्या स्पष्ट रूप से पहचानना आसान है, जो इस सुविधा के लाभ को बहुत कम कर देता है। – CodesInChaos

+2

@CodeInChaos: वास्तव में, यह एक ऐसा स्थान है जहां चेतावनी उचित हो सकती है। –

1

क्योंकि संकलक इस तरह की चीजों की जांच नहीं करेगा।

आप स्थापित कर लेते हैं एक कोड विश्लेषक Visual Studio में Resharper है जैसे कि यह अनंत पुनरावर्ती कॉल या उस मामले में आप कोड विश्लेषण विकल्प सक्षम की तरह sth की एक चेतावनी लाने के लिए।

20

डिफ़ॉल्ट रूप से यह समस्या के रूप में क्यों नहीं देखा जाता है?

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

void evil() { 
    if (somethingThatTurnsOutToAlwaysBeTrue) 
     evil(); 
} 

आदेश है कि क्या है कि एक समस्या है यह निर्धारित करने के लिए, संकलक करने की कोशिश करने के लिए है यह पता लगाएं कि स्थिति हमेशा सच होगी या नहीं। सामान्य मामले में, मुझे नहीं लगता कि यह निर्धारित करने के लिए कि यह अंततः प्रोग्राम बंद हो जाएगा या नहीं (यानी यह provably not computable है) यह निर्धारित करने से कहीं अधिक गणना योग्य है।

+17

+1। कंपाइलर्स परेशान नहीं हैं क्योंकि रोक समस्या सामान्य मामले में असंगत है। – Patrick87

+1

उसी तर्क से, एक कंपाइलर पहुंचने योग्य कोड के बारे में चेतावनी देने के लिए परेशान नहीं होगा। और फिर भी यह करता है - मामलों के एक विशेष सबसेट में। – harold

+0

@harold एरिक लिपर्ट के रूप में अच्छी तरह से समझाया गया, यह नीचे उबलता है चेतावनी उत्पन्न करने की लागत और लाभ के बारे में एक निर्णय। मैं यहां क्या कहने की कोशिश कर रहा था यह है कि मामूली मामला का पता लगाना बहुत उपयोगी नहीं लगता है, और अनौपचारिक मामले जहां एक चेतावनी उपयोगी होगी, मुश्किल या असंभव होने की संभावना है पता लगाएं। – Caleb

1

मुझे संदेह है कि संकलक संकलन समय पर एक रन-टाइम घटना (ढेर ओवरफ्लो) का पता लगा सकता है। अपने अंदर एक समारोह को कॉल करने के लिए कई वैध मामले हैं, रिकर्सन। लेकिन कंपाइलर रिकर्सन के बुरे मामलों से अच्छा कैसे पता लगा सकता है?

जब तक इसमें कुछ एआई नहीं जोड़ा जाता है, मुझे नहीं लगता कि एक कंपाइलर अच्छे और बुरे रिकर्सन के बीच अंतर का पता लगा सकता है, यह प्रोग्रामर का काम है।

2

संकलक या दुभाषिया को यह जानने का अनुमान है कि फ़ंक्शन क्या कर रहा है? कंपाइलर और दुभाषिया का दायरा वाक्य रचनात्मक कोड को संकलित या व्याख्या करना है - आपके कोड के अर्थशास्त्र की व्याख्या नहीं करना।

भले ही एक कंपाइलर ने इसकी जांच की हो, आप लाइन कहां खींचते हैं? क्या होगा यदि आपके पास एक पुनरावर्ती कार्य था जो हमेशा के लिए फैक्टोरियल की गणना करता था?

+1

कंपाइलर आपके फ़ंक्शन के बारे में बहुत कुछ जानता है। यह फ़ंक्शन में सभी कोड पथ जानता है। यह इस अर्थपूर्ण ज्ञान का उपयोग विश्लेषण करने के लिए करता है जैसे पहुंचने योग्य कोड का पता लगाने, एक चर सुनिश्चित करना सभी कोड पथों पर पढ़ने से पहले शुरू किया गया है, ... – CodesInChaos

3

किसी भी प्रोग्रामिंग भाषा के किसी भी कंपाइलर को संकलित कोड के अर्थशास्त्र के बारे में कोई भी विचार नहीं है। यह मान्य कोड है, हालांकि बेवकूफ है, इसलिए इसे संकलित किया जाएगा।

+0

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

0

जैसा कि आपने कंपाइलर का उल्लेख किया है, केवल सिंथेटिकल त्रुटियों की जांच करता है। रिकर्सिव फ़ंक्शन किसी भी त्रुटि को निष्पादित रूप से वैध w/o मान्य करता है।

रनटाइम के दौरान,

जब ढेर बहकर है यह ढेर अतिप्रवाह * कोड * की वजह से नहीं की वजह से एक त्रुटि फेंकता है।

रिकर्सिव फ़ंक्शन उचित रूप से मान्य है, लेकिन फिर कार्यान्वयन में हमें स्टैक भरने से पहले मूल्यों को वापस करने के लिए स्थिति जांच करने की आवश्यकता है।

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