मैंने हाल ही में एक कार्यक्रम में लिखा था, जब मैं अपने "व्यापार तर्क" कोड को तृतीय-पक्ष या प्रोजेक्ट एपीआई में अपवाद ट्रिगर करता था तो लॉग करना चाहता था। (स्पष्टीकरण के लिए, जब मैं किसी एपीआई का उपयोग अपवाद का कारण बनता हूं तो लॉग इन करना चाहता हूं। यह वास्तविक throw
से ऊपर कई फ्रेम हो सकता है, और वास्तविक catch
से नीचे कई फ्रेम हो सकते हैं (जहां अपवाद पेलोड का लॉगिंग हो सकता है।) Iकोई अपवाद ट्रिगर होने पर लॉग इन कैसे होना चाहिए?
void former_function()
{
/* some code here */
try
{
/* some specific code that I know may throw, and want to log about */
}
catch(...)
{
log("an exception occurred when doing something with some other data");
throw;
}
/* some code here */
}
संक्षेप में, एक अपवाद तब होता है,, एक कैच-ऑल खंड बनाने के त्रुटि लॉग इन करें, और फिर से फेंक: निम्नलिखित किया था। मेरे दिमाग में यह सुरक्षित है। मुझे सामान्य पकड़ में पता है-सभी को बुरा माना जाता है, क्योंकि किसी के पास कोई उपयोगी जानकारी प्राप्त करने के लिए अपवाद का संदर्भ नहीं है। हालांकि, मैं इसे फिर से फेंकने जा रहा हूं, इसलिए कुछ भी नहीं खो गया है।
अब, अपने आप पर यह ठीक था, लेकिन कुछ अन्य प्रोग्रामर ने इस कार्यक्रम को संशोधित किया, और उपरोक्त का उल्लंघन समाप्त कर दिया। विशेष रूप से, उन्होंने एक मामले में कोशिश-ब्लॉक में बड़ी मात्रा में कोड डाला, और दूसरे में 'फेंक' हटा दिया और 'वापसी' रखा।
अब मुझे लगता है कि मेरा समाधान भंगुर था; यह भविष्य-संशोधन-सबूत नहीं था।
मुझे एक बेहतर समाधान चाहिए जिसमें इन समस्याओं को न हो।
मेरे पास एक और संभावित समाधान है जिसमें उपर्युक्त मुद्दा नहीं है, लेकिन मुझे आश्चर्य है कि दूसरे इसके बारे में क्या सोचते हैं। यह आरए II, विशेष रूप से एक वस्तु "स्कोप से बाहर निकलें" अगर std::uncaught_exception
निर्माण पर सच नहीं है कि परोक्ष चलाता है का उपयोग करता है, फिर भी विनाश पर सत्य है:
#include <ciso646> // not, and
#include <exception> // uncaught_exception
class ExceptionTriggeredLog
{
private:
std::string const m_log_message;
bool const m_was_uncaught_exception;
public:
ExceptionTriggeredLog(std::string const& r_log_message)
: m_log_message(r_log_message),
m_was_uncaught_exception(std::uncaught_exception())
{
}
~ExceptionTriggeredLog()
{
if(not m_was_uncaught_exception
and std::uncaught_exception())
{
try
{
log(m_log_message);
}
catch(...)
{
// no exceptions can leave an destructor.
// especially when std::uncaught_exception is true.
}
}
}
};
void potential_function()
{
/* some code here */
{
ExceptionTriggeredLog exception_triggered_log("an exception occurred when doing something with some other data");
/* some specific code that I know may throw, and want to log about */
}
/* some code here */
}
मैं जानना चाहता हूँ:
- तकनीकी रूप से, क्या यह मजबूती से काम करेगा? प्रारंभ में ऐसा लगता है, लेकिन मुझे पता है कि
std::uncaught_exception
का उपयोग करने के बारे में कुछ चेतावनी हैं। - क्या मैं चाहता हूं कि पूरा करने के लिए एक और तरीका है?
नोट: मैंने इस प्रश्न को अद्यतन किया है। विशेष रूप से, मैं कर दिया है:
try
/catch
है कि शुरू में याद आ रही थी, जोड़ाlog
समारोह-कॉल के आसपास।- निर्माण पर
std::uncaught_exception
राज्य ट्रैकिंग को जोड़ा गया। इस मामले के खिलाफ यह गार्ड जहां यह ऑब्जेक्ट किसी अन्य विनाशक के 'प्रयास' ब्लॉक के अंदर बनाया गया है जो अपवाद स्टैक-अनइंडिंग के हिस्से के रूप में ट्रिगर किया जाता है। - नाम ऑब्जेक्ट बनाने के लिए नया 'संभावित_फंक्शन' तय किया गया है, अस्थायी ऑब्जेक्ट पहले जैसा नहीं है।
आपको शायद यह पता है, लेकिन आपको 'लॉग' को 'अस्वीकरण' या 'फेंक()' के रूप में घोषित करने की आवश्यकता होगी या इसे {try {'और'} पकड़ें (...) ' – utnapistim
@utnapistim अनुस्मारक के लिए धन्यवाद; मेरे सरल उदाहरण में यह 'फेंक() '/' noexcept' है, लेकिन सामान्य रूप से यह नहीं होगा, और' try'/'catch' होना चाहिए। –
आपके साथी को क्या रोकता है प्रोग्रामर ब्रेसिज़ के बाहर "बड़ी मात्रा में कोड" डालने से? या उन्हें हटा दें क्योंकि वे अनावश्यक प्रतीत होते हैं? मैं कोशिश करूंगा एक टिप्पणी जोड़ना * कृपया इस फेंक को वापसी के साथ प्रतिस्थापित न करें। यह काम नहीं करता है! *। –