2012-01-08 20 views
31

Concepts, जो इन उपकरणों को अनावश्यक प्रस्तुत करेगा, not part of C++11 हैं।टेम्पलेट-आधारित कोड के लिए उच्च गुणवत्ता वाले त्रुटि संदेश उत्पन्न करने के लिए उपकरण?

  • STLFilt एक विकल्प होता लेकिन यह अब बनाए रखा नहीं जाता है।

  • Clang अभिव्यक्तित्मक निदान देने का दावा करता है हालांकि महत्वपूर्ण C++11 features अभी तक उपलब्ध नहीं हैं।

  • colorgcc 1999.

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

अगर मैं सी ++ 11 पर छोड़ देता हूं, तो मेरे पास सी ++ 98 के लिए कौन से विकल्प हैं?


संबंधित प्रश्न:

+1

कौन सी सी ++ 11 विशेषताएं आपको विशेष रूप से आवश्यक है कि क्लैंग अभी तक नहीं है? –

+1

@ बेनवोइग [क्लैंग वेबसाइट के अनुसार] (http://clang.llvm.org/cxx_status.html) प्रारंभकर्ता सूचियां, सी ++ 0x लैम्ब्डास के लिए नया शब्द, कन्स्ट्रक्टरों को विरासत, सार्वभौमिक चरित्र का नाम शाब्दिक, उपयोगकर्ता परिभाषित अक्षर उपलब्ध नहीं है। क्या क्लैंग वास्तव में टेम्पलेट्स के लिए बेहतर त्रुटि संदेश प्रदान करता है? मैंने कभी कोशिश नहीं की है। – Ali

+0

अवधारणाओं को कुछ भी करने के साथ क्या करना है? जैसा कि आप इंगित करते हैं, वे भाषा में नहीं हैं। –

उत्तर

16

चलो एक जवाब पर एक चाकू है (मैं इस समुदाय विकी चिह्नित इसलिए हम एक अच्छी प्रतिक्रिया एक साथ हो) ..

मैं टेम्पलेट्स के साथ लंबे समय से काम कर रहा हूं और त्रुटि संदेश आम तौर पर किसी तरह से या किसी अन्य में सुधार हुआ है:

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

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

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

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

9

मुझे पता है कि यह आपके जैसा सहायक नहीं हो सकता है, लेकिन मुझे टेम्पलेट त्रुटि संदेशों के खिलाफ सबसे अच्छा टूल मिला है ज्ञान

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

std::vector<std::unique_ptr<int>> foo; 
std::vector<std::unique_ptr<int>> bar = foo; 

unique_ptr copyable नहीं है,:

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

1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(48): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' 
1>   with 
1>   [ 
1>    _Ty=int 
1>   ] 
1>   C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\memory(2347) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr' 
1>   with 
1>   [ 
1>    _Ty=int 
1>   ] 
1>   C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(197) : see reference to function template instantiation 'void std::_Construct<std::unique_ptr<_Ty>,const std::unique_ptr<_Ty>&>(_Ty1 *,_Ty2)' being compiled 
1>   with 
1>   [ 
1>    _Ty=int, 
1>    _Ty1=std::unique_ptr<int>, 
1>    _Ty2=const std::unique_ptr<int> & 
1>   ] 
1>   C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(196) : while compiling class template member function 'void std::allocator<_Ty>::construct(std::unique_ptr<int> *,const _Ty &)' 
1>   with 
1>   [ 
1>    _Ty=std::unique_ptr<int> 
1>   ] 
1>   C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(421) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled 
1>   with 
1>   [ 
1>    _Ty=std::unique_ptr<int> 
1>   ] 
1>   C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(481) : see reference to class template instantiation 'std::_Vector_val<_Ty,_Alloc>' being compiled 
1>   with 
1>   [ 
1>    _Ty=std::unique_ptr<int>, 
1>    _Alloc=std::allocator<std::unique_ptr<int>> 
1>   ] 
1>   main.cpp(19) : see reference to class template instantiation 'std::vector<_Ty>' being compiled 
1>   with 
1>   [ 
1>    _Ty=std::unique_ptr<int> 
1>   ] 

इस के माध्यम से Sifting वहाँ सुराग हैं: आदर्श त्रुटि संदेश

main.cpp(20): cannot construct 'bar' from 'foo': foo's template type is non-copyable

इसके बजाय हो सकता है, VS2010 निम्न त्रुटि देता है। पहला खंड std::unique_ptr<int> का एक निजी सदस्य पहुंच का संदर्भ देता है। दूसरा खंड, यदि आप स्रोत रेखा पर क्लिक करते हैं, तो unique_ptr की कॉपी कन्स्ट्रक्टर पर इंगित करता है, जिसे private: विनिर्देशक के नीचे घोषित किया जाता है। तो अब हम जानते हैं कि हमने एक अद्वितीय_ptr की प्रतिलिपि बनाने की कोशिश की है जिसकी अनुमति नहीं है। अनुभाग 3, 4 और 5 बस बॉयलरप्लेट कोड को इंगित करें - यह सिर्फ शोर है। धारा 6 का कहना है, "क्लास टेम्पलेट इंस्टेंटेशन के संदर्भ देखें" std :: _ वेक्टर_वल < _Ty, _Alloc> 'संकलित किया जा रहा है "। दूसरे शब्दों में, यह त्रुटि वेक्टर के टेम्पलेट कोड में हुई। अंतिम खंड सबसे दिलचस्प है: यह सीधे आपके स्रोत कोड में foo घोषित लाइन पर इंगित करता है - यह पता लगाया गया है कि आपके स्रोत कोड में त्रुटि से उत्पन्न हुआ है!

तो सुराग को जोड़कर:

  • यह foo में निकलती है,
  • यह वेक्टर कोड में निकलती है,
  • यह एक unique_ptr जिसकी अनुमति नहीं है नकल करने की कोशिश करता।
  • निष्कर्ष: वेक्टर ने अपने तत्वों में से एक को कॉपी करने की कोशिश की, जिसकी अनुमति नहीं है। foo के लिए समीक्षा कोड और एक प्रतिलिपि बनाने के लिए कुछ भी जांचें।

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

+1

+1। दुर्भाग्यवश, आप अपने पहले पैराग्राफ में सही हैं। यह सी ++ को सही तरीके से उपयोग करने के लिए एक बहुत ही कठिन भाषा बनाता है (और यह केवल हिमशैल की नोक है: उदाहरण के लिए, सी ++ 11 में अपवाद सुरक्षा विचार मुझे दर्दनाक सिरदर्द देता है, और मैं खुद को एक अनुभवी सी ++ प्रोग्रामर मानता हूं)। प्रश्न के सबसे उपयोगी उत्तर, सी ++ भाषा की वर्तमान स्थिति को ध्यान में रखते हुए, वास्तव में * "इसके साथ सौदा करते हैं, सी ++ का उपयोग करके आप जिस कीमत का भुगतान करते हैं, उसे नियंत्रण की अवधि में लाभों के मुकाबले वजन कम किया जाना चाहिए" *। –

+0

सैद्धांतिक रूप से, एसएफआईएनएई और 'static_assert' (या गैर-सी ++) के साथ घूमने के तरीके में अवधारणाओं को लागू करके विशेष संदेशों या भाषा-स्तर की अवधारणाओं (* विशेष रूप से * सी ++ में) के बिना भी उन संदेशों को आसानी से सुधार किया जा सकता है (या गैर-सी ++ 11 समकक्ष)। मुझे लगता है कि आप सी ++ 11 में ['is_copy_constructible'] (http://en.cppreference.com/w/cpp/types/is_copy_constructible) के साथ परीक्षण कर सकते हैं और उसे 'ऑपरेटर =' (या किसी भी ऑपरेटर के अंदर फेंक दें) कॉपी करने योग्य टाइप करें)। – Xeo

+0

हाँ, चलिए जल्द ही एसटीएल में कोड सुधार के लिए आशा करते हैं ... – AshleysBrain

4

मुझे क्लैंग को भारी टेम्पलेट कोड के लिए सबसे अच्छा त्रुटि संदेश उत्पन्न करने के लिए मिला है। बेशक ज्यादातर मामलों में वर्बोसिटी अपरिहार्य है, लेकिन यह ज्यादातर समय जीसीसी या एमएसवीसी से बेहतर है। यहां उदाहरण के कोड AshleysBrain द्वारा पोस्ट की गई के लिए बजना त्रुटि संदेश है:

$ clang++ -std=c++11 -stdlib=libc++ -o dummy dummy.cpp 
In file included from dummy.cpp:1: 
In file included from /usr/include/c++/v1/vector:243: 
In file included from /usr/include/c++/v1/__bit_reference:15: 
In file included from /usr/include/c++/v1/algorithm:594: 
/usr/include/c++/v1/memory:1425:36: error: calling a private constructor of class 'std::__1::unique_ptr<int, 
     std::__1::default_delete<int> >' 
       ::new ((void*)__p) _Tp(_STD::forward<_Args>(__args)...); 
           ^
/usr/include/c++/v1/memory:1358:14: note: in instantiation of function template specialization 
     'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > 
     >::__construct<std::__1::unique_ptr<int, std::__1::default_delete<int> >, std::__1::unique_ptr<int, 
     std::__1::default_delete<int> > &>' requested here 
      {__construct(__has_construct<allocator_type, pointer, _Args...>(), 
      ^
/usr/include/c++/v1/vector:781:25: note: in instantiation of function template specialization 
     'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > 
     >::construct<std::__1::unique_ptr<int, std::__1::default_delete<int> >, std::__1::unique_ptr<int, 
     std::__1::default_delete<int> > &>' requested here 
     __alloc_traits::construct(__a, _STD::__to_raw_pointer(this->__end_), *__first); 
         ^
/usr/include/c++/v1/vector:924:9: note: in instantiation of function template specialization 
     'std::__1::vector<std::__1::unique_ptr<int, std::__1::default_delete<int> >, 
     std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > 
     >::__construct_at_end<std::__1::unique_ptr<int, std::__1::default_delete<int> > *>' requested here 
     __construct_at_end(__x.__begin_, __x.__end_); 
     ^
dummy.cpp:7:37: note: in instantiation of member function 'std::__1::vector<std::__1::unique_ptr<int, 
     std::__1::default_delete<int> >, std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > 
     >::vector' requested here 
     std::vector<unique_ptr<int>> bar = foo; 
             ^
/usr/include/c++/v1/memory:1997:5: note: declared private here 
    unique_ptr(const unique_ptr&); 
    ^
1 error generated. 

यह अभी भी लंबी और बदसूरत है, लेकिन मेरी राय में अधिक स्पष्ट के बारे में क्या/समस्या है, जहां।

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