C ++ टेम्प्लेट त्रुटि संदेश इतने भयावह क्यों हैं?


28

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

template <class T>
void dosomething(T& x) { x += 5; }

यदि ऑपरेटर का Tसमर्थन नहीं करता है +=, तो संकलक एक त्रुटि संदेश उत्पन्न करेगा। और अगर यह कहीं एक पुस्तकालय के भीतर गहरा होता है, तो त्रुटि संदेश हजारों पंक्तियों का हो सकता है।

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

def dosomething(x):
   x.foo()

यहाँ, यदि xकोई foo()विधि नहीं है , तो पायथन दुभाषिया एक अपवाद फेंकता है, और समस्या का संकेत करने वाले एक बहुत स्पष्ट त्रुटि संदेश के साथ एक स्टैक ट्रेस प्रदर्शित करता है। भले ही त्रुटि तब तक न हो, जब तक कि इंटरप्रिटर कुछ लाइब्रेरी फ़ंक्शन के अंदर गहरा हो, रनटाइम-एरर मैसेज अभी भी कहीं भी पास में नहीं है क्योंकि एक विशिष्ट C ++ कंपाइलर द्वारा पढ़े गए अपठनीय उल्टी के रूप में बुरा है। तो जो गलत हुआ उसके बारे में C ++ कंपाइलर अधिक स्पष्ट क्यों नहीं हो सकता है? कुछ C ++ टेम्पलेट त्रुटि संदेश शाब्दिक रूप से मेरे कंसोल विंडो को 5 सेकंड के लिए स्क्रॉल करने का कारण क्यों बनते हैं?


6
कुछ कंपाइलरों में भयावह त्रुटि संदेश होते हैं, लेकिन अन्य वास्तव में अच्छे होते हैं ( clang++विंक विंक)।
बेंजामिन बैनियर

2
तो आप संकलन-समय पर विफल होने के बजाय, ग्राहक के हाथों रनटाइम, शिप, फेल होने के अपने कार्यक्रमों को प्राथमिकता देंगे?
पी शेव्ड

13
@ फावड़ा, नहीं। यह प्रश्न रनटाइम के फायदे / नुकसान के बारे में नहीं है।
Channel72

1
बड़ी C ++ टेम्पलेट त्रुटियों के एक उदाहरण के रूप में, FWIW: codegolf.stackexchange.com/a/10470/7174
kebs

जवाबों:


28

टेम्प्लेट त्रुटि संदेश कुख्यात हो सकते हैं, लेकिन किसी भी तरह से हमेशा लंबे और अपठनीय नहीं होते हैं। इस स्थिति में, संपूर्ण त्रुटि संदेश (gcc से) है:

test.cpp: In function void dosomething(T&) [with T = X]’:
test.cpp:11:   instantiated from here
test.cpp:6: error: no match for operator+=’ in x += 5

अपने पायथन उदाहरण के रूप में, आपको टेम्पलेट तात्कालिक बिंदुओं का "स्टैक ट्रेस" और समस्या को इंगित करने वाला स्पष्ट त्रुटि संदेश मिलता है।

कभी-कभी, विभिन्न कारणों से टेम्प्लेट-संबंधी त्रुटि संदेश अधिक समय तक प्राप्त कर सकते हैं:

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

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

इसके अलावा, रनटाइम पर जाँच करने का अर्थ है कि यह पहली त्रुटि पर प्रोग्राम बंद हो जाएगा, केवल एक संदेश प्रदर्शित करना। एक कंपाइलर अपने सामने आने वाली सभी त्रुटियों को प्रदर्शित कर सकता है, जब तक कि वह हार न मान ले; कम से कम C ++ में, यह फ़ाइल में पहली त्रुटि पर नहीं रुकना चाहिए, क्योंकि यह बाद की त्रुटि का परिणाम हो सकता है।


4
क्या आप बाद में हुई त्रुटि के परिणामस्वरूप त्रुटि का उदाहरण दे सकते हैं?
रुस्लान

12

कुछ स्पष्ट कारणों में शामिल हैं:

  1. इतिहास। जब gcc, MSVC, इत्यादि नए थे, तो वे बेहतर त्रुटि संदेशों का उत्पादन करने के लिए डेटा स्टोर करने के लिए बहुत से अतिरिक्त स्थान का उपयोग नहीं कर सकते थे। मेमोरी काफी दुर्लभ थी कि वे बस नहीं कर सकते थे।
  2. सालों तक, उपभोक्ताओं ने त्रुटि संदेश की गुणवत्ता को नजरअंदाज किया, इसलिए विक्रेताओं ने ज्यादातर ऐसा किया।
  3. कुछ कोड के साथ, कंपाइलर कोड में बाद में वास्तविक त्रुटियों को फिर से सिंक्रनाइज़ और निदान कर सकता है। टेम्प्लेट में त्रुटियां इतनी बुरी तरह से घटती हैं कि पहले का कुछ भी लगभग हमेशा बेकार हो जाता है।
  4. टेम्पलेट्स के सामान्य लचीलापन अनुमान लगाना क्या आप इसे कठिन बना देता है शायद जब अपने कोड में कोई त्रुटि है मतलब है।
  5. टेम्प्लेट के अंदर, एक नाम का अर्थ टेम्पलेट के संदर्भ, और तात्कालिकता के संदर्भ दोनों पर निर्भर करता है, और तर्क पर निर्भर लुकअप अभी भी अधिक संभावनाएं जोड़ सकता है।
  6. फंक्शन ओवरलोडिंग बहुत सारे उम्मीदवारों को प्रदान कर सकती है , जो किसी विशेष फ़ंक्शन कॉल का उल्लेख कर सकते हैं, और कुछ संकलक (जैसे, जीसीसी) उन पर पूरी तरह से सूचीबद्ध करते हैं जब एक अस्पष्टता होती है।
  7. कई कोडर्स जो सामान्य मानदंड का उपयोग किए बिना कभी भी विचार नहीं करेंगे कि पारित मान आवश्यकताओं को पूरा करते हैं, यहां तक ​​कि टेम्पलेट मापदंडों की जांच करने का भी प्रयास न करें (और मुझे कबूल करना होगा, मैं खुद इस ओर जाता हूं)।

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

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


9

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

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

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