2011-01-31 22 views
7

से प्राप्त करना मैं अपनी लॉग फ़ाइलों में विशिष्ट जानकारी जोड़ने के लिए std :: अपवाद से प्राप्त करना चाहता हूं, लेकिन मैं यह नहीं समझ सकता कि std :: अपवाद से .what() तक कैसे पहुंचे।std :: अपवाद

इसके अलावा, मुझे पता है कि मेरे अपवाद हैंडलर में एक स्ट्रिंग बनाने के लिए असुरक्षित है, लेकिन मैं इस विषय पर एक विशेषज्ञ नहीं हूं, तो कुछ सुरक्षित विकल्प क्या हैं?

struct Exception : public std::exception, private boost::noncopyable 
{ 
    public: 
     Exception(std::string msg) 
      : message(msg) 
     {} 
     ~Exception() 
     {} 

     virtual const char* what() const throw 
     { 
      std::string what = message + // and now what? base.what() 
      LOG(what); // write to log file 
      return what.c_str(); 
     } 

    private: 
     std::string message; 
}; 

संपादित करें: मैं सच में मेरे सवाल का गलत तरीके से कहा है। मुझे सुरक्षा में दिलचस्पी है, मैंने सोचा कि लॉगिंग के लिए अधिक डेटा होना अच्छा लगेगा। मैं गलत था।

अब, मैं खराब स्ट्रॉल के कारण संदेश स्ट्रिंग द्वारा फेंकने वाले Bad_alloc के बारे में इतना पागल नहीं हूं, इसके बजाय मुझे एक साफ संदेश होगा। कहा जा रहा है कि मैंने कुछ सामान फिर से लिखा है:

struct Exception : public std::exception 
{ 
    public: 
     Exception(std::string msg) 
      : message(msg) 
     {} 
     ~Exception() 
     {} 

     virtual const char* what() const throw 
     { 
      LOG(what); // write to log file 
      return what.c_str(); 
     } 

    private: 
     std::string message; 
}; 

अभी भी उस कोड के बारे में कोई बड़ी चिंता है? LOG() std :: अपवाद को फेंक देता है I मामला कुछ गलत हो जाता है, क्योंकि मैं व्युत्पन्न अपवाद वर्ग द्वारा लॉग कॉलिंग का अनंत लूप नहीं चाहता था, और वह वर्ग फिर से लॉग को कॉल करता है जो एक ही अपवाद को फिर से उत्पन्न करेगा। क्या यह काम जैसा मैं चाहता हूं, या मेरे व्युत्पन्न क्लास कॉल टर्मिनेट() में लॉगिंग अपवाद होगा या कोर डंप का कारण बन जाएगा?

+2

पुन: सुरक्षित विकल्प। यह एक बड़ा सवाल है। अपने स्वयं के प्रश्न के लिए उपयुक्त है। –

+1

स्टैक ओवरफ़्लो में आपका स्वागत है। ऐसा लगता है कि आप * दो * प्रश्न पूछ रहे हैं (जिसका अर्थ है कि आपको दो अलग-अलग पोस्ट करना चाहिए)। एक पूछता है कि बेस क्लास से विरासत विधि को कैसे कॉल किया जाए, और दूसरे स्ट्रिंग के बिना अपवाद संदेश को स्टोर करने के लिए कहता है (संभवतः क्योंकि आप स्मृति आवंटित नहीं करना चाहते हैं और 'bad_alloc' का जोखिम लेना चाहते हैं)। विशेष रूप से 'std :: अपवाद' से प्राप्त करने के साथ वास्तव में कुछ भी नहीं है। अलग, विशिष्ट प्रश्न अधिक वर्णनात्मक प्रश्न शीर्षक और अधिक उपयोगी उत्तरों की ओर ले जाते हैं। कृपया इस सवाल को विभाजित करने पर विचार करें। –

+2

यदि आपका कोड टाइप अपवाद ("...") का अपवाद फेंकता है, तो आप std :: अपवाद :: क्या() लौटने की उम्मीद करते हैं? मुझे नहीं लगता कि इसमें कुछ भी उपयोगी होगा (यदि इसमें कुछ भी शामिल है)। मैं बस संदेश.c_str() लौटने का सुझाव दूंगा। – Ferruccio

उत्तर

9

संपादित के साथ किसी भी समस्या थी। मैं इस जवाब पर उस दस्तावेज की सिफारिश करता हूं।


सबसे पहले, अपवाद को प्रतिलिपि बनाने योग्य एक बुरा विचार है। जब आप

// could be any exception, doesn't matter. 
throw Exception(...); 

रनटाइम उस वस्तु की एक प्रति को एक विशेष स्थान पर बनाता है। कुछ कंपाइलर्स इसे अनुकूलित कर सकते हैं और उस स्थान पर मूल ऑब्जेक्ट बना सकते हैं, लेकिन The C++ Programming Language कहता है कि यह एक प्रति है, और मुझे यह भी विश्वास है कि मानक क्या कहता है, हालांकि मुझे यकीन नहीं है। आप अपने वर्तमान माहौल में इससे दूर हो सकते हैं, लेकिन यह हमेशा मामला नहीं हो सकता है।

फिर, बाकी सब कुछ इस बात पर निर्भर करता है कि आप कोने के मामलों के साथ कितने पागल हैं।

स्मृति आवंटन भाग अपवाद खंड (यानी कन्स्ट्रक्टर) में ज्यादातर flaky है। इस स्मृति आवंटन विफल यदि ऐसा होता है (यानी std::bad_alloc फेंक दिया जाता है), दो संभावनाएं देखते हैं, कैसे आप अपने throw बयान लिखने के आधार पर:

  1. std::stringthrow बयान से पहले बनाई गई है, std::bad_alloc की जगह अपवाद आप सोचा था कि तुम करोगी उठाओ, बुरी तरह से रिपोर्ट की समस्या है।
  2. std::string कन्स्ट्रक्टर कॉल में इनलाइन बनाया गया है। यदि इसे मानक द्वारा "अपवाद हैंडलिंग के दौरान" माना जाता है, तो std::unexpected()/std::terminate() लागू किया जाएगा और आपको मूल रूप से कोर डंप मिल जाएगा।

किसी भी मामले में, ऐसा लगता है कि आपको अपनी त्रुटि की रिपोर्ट करने का वांछित प्रभाव नहीं मिलेगा।

मैं हमेशा कुछ प्रकार की अस्थायी स्थिति बनाने की अनुशंसा करता हूं जो कि कन्स्ट्रक्टर में स्मृति आवंटित नहीं करता है और त्रुटि की रिपोर्ट करने वाली स्ट्रिंग बनाने के लिए std::what() पर कॉल की प्रतीक्षा करता है, लेकिन यह अभी भी केस # 1 का कारण बन सकता है। यह सुनिश्चित करने के लिए कि कुछ नहीं होता है, आप कुछ संकलन-समय निर्धारित बफर आकार का सहारा ले सकते हैं।

कई लोग आपको बताएंगे कि उन्हें रचनाकारों में स्ट्रिंग आवंटित करने में कभी समस्या नहीं हुई है क्योंकि यह संभवतः std::bad_alloc तब तक उठाया जाएगा जब तक मूल अपवाद std::bad_alloc पहले स्थान पर नहीं था। इसलिए, यह आपके पायरानिया के स्तर पर निर्भर करता है।

+0

नोट: मेरे पास अच्छी तरह से संदर्भ देने के लिए हाथ में पुस्तक नहीं है ... –

4

मैं आपके कोड के साथ असंख्य समस्याओं में नहीं जाऊंगा क्योंकि यह कीड़े का एक बड़ा हिस्सा है। लेकिन यहां बताया गया है कि आप बेस क्लास विधि कैसे कॉल करते हैं:

std::exception::what() 
+0

बीटीडब्लू में रहूंगा, मैंने आपके स्थानीय चर का नाम बदल दिया है। –

+1

वापसी मूल्य वापसी प्रकार से मेल नहीं खाता है? – UncleBens

+0

@ यूंकल: मेरी आलस्य को इंगित करने के लिए धन्यवाद। :) फिक्स्ड। –

-1

दूसरे भाग के लिए। मेरे पास कई सौ क्लोक हैं जो 100 प्लेटफार्मों पर चलते हैं जिनमें std :: स्ट्रिंग सदस्यों के साथ std :: अपवाद व्युत्पन्न कक्षा है। इस उत्तर लेखन के बाद से, मैं बूस्ट दस्तावेज़ में Error and Exception Handling खंड पर ठोकर खाई है: कभी इसके

class myex: public std::exception 
{ 
public: 
    std::string m_msg; 
    std::string m_className; 
    int m_rc; 
... 
3

इस प्रश्न का उत्तर तब तक है जब तक कि आपने स्पष्ट रूप से मूल्य निर्धारित नहीं किया है कि क्या() std :: अपवाद से वापस आना चाहिए, तो आप इसे कॉल नहीं करना चाहते हैं। इस तथ्य का तथ्य यह है कि यह उन तरीकों से व्यवहार करने जा रहा है जिनकी आप उम्मीद नहीं कर सकते हैं और अलग-अलग कार्यान्वयन पर असमान रूप से नहीं हो सकते हैं।

ध्यान दें कि मानक स्ट्रिंग मान प्रदान करने के लिए std :: अपवाद में कोई कार्यक्षमता प्रदान नहीं करता है। उन कार्यान्वयन जो वास्तव में std :: अपवाद :: कॉल() को कक्षा से अतिरिक्त, गैर-मानक कार्यक्षमता जोड़ने से उपयोगी जानकारी प्रदान करते हैं। उदाहरण के लिए, एमएसवीसी में exception(char const* const&) कन्स्ट्रक्टर है। यह मानक में नहीं है और आप शायद इस पर निर्भर नहीं होना चाहते हैं।

आपकी बेहतर शर्त कभी भी std :: अपवाद :: किसी व्युत्पन्न वर्ग से क्या नहीं कॉल करना है। निश्चित रूप से, अपने कस्टम संस्करणों में अपवाद करें जो std :: अपवाद के तहत चीजों को उप-वर्गीकृत करते हैं, लेकिन प्रत्यक्ष डेरिवेटिव में ऐसा न करें।

यदि आप सीधे इस फ़ंक्शन को कॉल करने का आग्रह करते हैं तो आप NULL के लिए बेहतर जांच करेंगे क्योंकि आप शायद यही प्राप्त करने जा रहे हैं।

+0

+1 अच्छे उत्तर के लिए, लेकिन आपने अपने वास्तविक प्रश्न का उत्तर नहीं दिया जिसके अपवादों के साथ कुछ भी नहीं है। बेस क्लास विधि कैसे कॉल करें? –

+0

यदि आप ऐसा कहते हैं, जॉन। –

+0

धन्यवाद नोहा, @ जॉन, मुझे लगता है कि मैंने वास्तव में सवाल गलत तरीके से पूछा था। मैं सुरक्षा में interessted हूँ, मैंने सोचा कि मैं बेस क्लास से लॉगिंग के लिए और अधिक डेटा हो सकता है। लगता है कि मैं पूरी तरह से गलत था – cppanda

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