कई तरीके हैं, लेकिन पहले आपको यह समझने की आवश्यकता है कि ऑब्जेक्ट क्लीनअप क्यों महत्वपूर्ण है, और इसलिए इसका कारण std::exitसी ++ प्रोग्रामर्स के बीच हाशिए पर है।
RAII और स्टैक अनवाइंडिंग
C ++ RAII नामक एक मुहावरे का उपयोग करता है , जिसका साधारण अर्थ है कि वस्तुओं को निर्माणकर्ता में आरंभीकरण करना चाहिए और विध्वंसक में सफाई करना चाहिए। उदाहरण के लिए, std::ofstreamक्लास निर्माणकर्ता के दौरान फ़ाइल खोल सकता है, फिर उपयोगकर्ता उस पर आउटपुट ऑपरेशन करता है, और अंत में अपने जीवन चक्र के अंत में, आमतौर पर इसके दायरे से निर्धारित होता है, विध्वंसक को कहा जाता है कि अनिवार्य रूप से फ़ाइल को बंद कर देता है और फ्लश करता है डिस्क में कोई भी लिखित सामग्री।
यदि आप विध्वंसक को फ़ाइल को फ्लश और बंद करने के लिए नहीं आते हैं तो क्या होगा? कौन जाने! लेकिन संभवत: यह वह सभी डेटा नहीं लिखेगा जो इसे फाइल में लिखना चाहिए था।
उदाहरण के लिए इस कोड पर विचार करें
#include <fstream>
#include <exception>
#include <memory>
void inner_mad()
{
throw std::exception();
}
void mad()
{
auto ptr = std::make_unique<int>();
inner_mad();
}
int main()
{
std::ofstream os("file.txt");
os << "Content!!!";
int possibility = /* either 1, 2, 3 or 4 */;
if(possibility == 1)
return 0;
else if(possibility == 2)
throw std::exception();
else if(possibility == 3)
mad();
else if(possibility == 4)
exit(0);
}
प्रत्येक संभावना में क्या होता है:
- संभावना 1: रिटर्न अनिवार्य रूप से वर्तमान फ़ंक्शन स्कोप को छोड़ देता है, इसलिए यह
osइस तरह से अपने डिस्ट्रक्टर को कॉल करने और डिस्क को फाइल को फ्लश और बंद करके उचित सफाई करने के जीवन चक्र के अंत के बारे में जानता है ।
- संभावना 2: अपवाद को फेंकना वर्तमान दायरे में वस्तुओं के जीवन चक्र का भी ध्यान रखता है, इस प्रकार उचित सफाई ...
- संभावना 3: यहां स्टैक अनइंडिंग कार्रवाई में प्रवेश करती है! भले ही अपवाद को फेंक दिया गया हो
inner_mad, फिर भी अनइन्डर जाएगा, हालांकि ढेर madऔर mainउचित सफाई करने के लिए, सभी वस्तुओं को सही तरीके से नष्ट किया जा रहा है, जिसमें शामिल हैं ptrऔर os।
- संभावना 4: खैर, यहाँ?
exitएक C फ़ंक्शन है और यह C ++ मुहावरों के बारे में पता नहीं है और न ही संगत है। यह आपकी वस्तुओं पर सफाई का प्रदर्शन नहीं करता है , जिसमें osबहुत ही गुंजाइश भी शामिल है। तो आपकी फ़ाइल ठीक से बंद नहीं होगी और इस कारण से सामग्री कभी भी उसमें नहीं लिखी जा सकती है!
- अन्य संभावनाएँ: यह सिर्फ एक चीरा लगाकर मुख्य संभावना छोड़ देगा,
return 0इस प्रकार संभावना 1, अर्थात उचित सफाई के समान प्रभाव होगा।
लेकिन जो मैंने अभी आपको (मुख्यतः 2 और 3 की संभावनाएँ) बताई हैं, उनके बारे में कुछ निश्चित न करें; पढ़ना जारी रखें और हमें पता चलेगा कि एक उचित अपवाद आधारित सफाई कैसे करें।
अंत करने के लिए संभव तरीके
मुख्य से लौटें!
जब भी संभव हो आपको ऐसा करना चाहिए; हमेशा मुख्य से एक उचित निकास स्थिति को वापस करके अपने कार्यक्रम से वापस आना पसंद करें।
आपके प्रोग्राम का कॉलर, और संभवतः ऑपरेटिंग सिस्टम, यह जानना चाह सकता है कि आपका प्रोग्राम क्या करने वाला था, सफलतापूर्वक किया गया था या नहीं। इसी कारण से आपको या तो शून्य पर लौटना चाहिए या EXIT_SUCCESSयह संकेत देने के लिए कि कार्यक्रम सफलतापूर्वक समाप्त हो गया है और EXIT_FAILUREकार्यक्रम को असफल रूप से समाप्त करने का संकेत देने के लिए, वापसी मूल्य का कोई अन्य रूप कार्यान्वयन-परिभाषित है ( .518.5 / 8 )।
हालाँकि आप कॉल स्टैक में बहुत गहरे हो सकते हैं, और यह सब वापस आना दर्दनाक हो सकता है ...
[मत करो] एक अपवाद न फेंकें
किसी अपवाद को फेंकना किसी भी पिछले दायरे में हर वस्तु के विध्वंसक को कॉल करके स्टैक अनइंडिंग का उपयोग करके उचित ऑब्जेक्ट क्लीनअप करेगा।
लेकिन यहाँ पकड़ है ! यह कार्यान्वित-परिभाषित है कि क्या स्टैक अनइंडिंग किया जाता है जब फेंक दिया गया अपवाद नहीं पकड़ा जाता है (कैच (...) क्लॉज द्वारा) या यहां तक कि अगर आपके पास noexceptकॉल स्टैक के बीच में कोई फ़ंक्शन है। इस में कहा गया है §15.5.1 [except.terminate] :
कुछ स्थितियों में अपवाद हैंडलिंग को कम सूक्ष्म त्रुटि हैंडलिंग तकनीकों के लिए छोड़ दिया जाना चाहिए। [नोट: ये स्थितियाँ हैं:
[...]
- जब अपवाद हैंडलिंग तंत्र एक फेंके गए अपवाद (15.3) के लिए हैंडलर नहीं ढूंढ सकता है, या जब हैंडलर (15.3) की खोज किसी फ़ंक्शन के सबसे बाहरी ब्लॉक का सामना करती है,noexcept जो कि एक अनिर्दिष्टता (अपवाद) (15.4) की अनुमति नहीं देता है, या [...]
[...]
ऐसे मामलों में, std :: terminate () कहा जाता है (18.8.3)। ऐसी स्थिति में जहां कोई मिलान करने वाला हैंडलर नहीं मिलता है, यह कार्यान्वयन-परिभाषित है कि क्या स्टैक :: टर्मिनेट () कहा जाता है इससे पहले कि स्टैक निराधार है या नहीं [...]
इसलिए हमें इसे पकड़ना होगा!
एक अपवाद को फेंक दो और इसे मुख्य रूप से पकड़ लो!
चूंकि बिना किसी अपवाद के स्टैक अनइंडिंग नहीं किया जा सकता है (और परिणामस्वरूप उचित सफाई नहीं करेगा) , हमें मुख्य में अपवाद को पकड़ना चाहिए और फिर एक निकास स्थिति ( EXIT_SUCCESSया EXIT_FAILURE) वापस करना चाहिए ।
तो संभवतः एक अच्छा सेटअप होगा:
int main()
{
/* ... */
try
{
// Insert code that will return by throwing a exception.
}
catch(const std::exception&) // Consider using a custom exception type for intentional
{ // throws. A good idea might be a `return_exception`.
return EXIT_FAILURE;
}
/* ... */
}
[मत करो] एसटीडी :: बाहर निकलें
यह किसी भी प्रकार के स्टैक अनइंडिंग का प्रदर्शन नहीं करता है, और स्टैक पर कोई भी जीवित वस्तु अपने संबंधित डिस्ट्रक्टर को सफाई करने के लिए नहीं बुलाएगी।
यह §3.6.1 / 4 में लागू किया गया है [basic.start.init] :
वर्तमान ब्लॉक को छोड़कर कार्यक्रम को समाप्त करना (जैसे, फ़ंक्शन std :: exit (int) (18.5) कॉल करके स्वचालित भंडारण अवधि (12.4) के साथ किसी भी ऑब्जेक्ट को नष्ट नहीं करता है । यदि std :: exit को किसी वस्तु के विनाश के दौरान स्थैतिक या थ्रेड स्टोरेज अवधि के दौरान प्रोग्राम को समाप्त करने के लिए कहा जाता है, तो प्रोग्राम में अपरिभाषित व्यवहार होता है।
अब इसके बारे में सोचो, आप ऐसा क्यों करेंगे? आपने कितनी वस्तुओं को नुकसान पहुँचाया है?
अन्य [के रूप में बुरा] विकल्प
एक कार्यक्रम (दुर्घटनाग्रस्त होने के अलावा) को समाप्त करने के अन्य तरीके हैं , लेकिन वे अनुशंसित नहीं हैं। सिर्फ स्पष्टीकरण के लिए वे यहां प्रस्तुत होने जा रहे हैं। ध्यान दें कि सामान्य प्रोग्राम समाप्ति का मतलब स्टैक अनइंडिंग नहीं है, लेकिन ऑपरेटिंग सिस्टम के लिए एक ठीक स्थिति है।
std::_Exit एक सामान्य कार्यक्रम समाप्ति का कारण बनता है, और यह बात है।
std::quick_exitएक सामान्य कार्यक्रम समाप्ति का कारण बनता है और std::at_quick_exitहैंडलर को बुलाता है, कोई अन्य सफाई नहीं की जाती है।
std::exitएक सामान्य कार्यक्रम समाप्ति का कारण बनता है और फिर std::atexitहैंडलर को बुलाता है। अन्य प्रकार के क्लीनअप का प्रदर्शन किया जाता है जैसे स्थैतिक वस्तुओं को विध्वंसक कहना।
std::abortएक असामान्य कार्यक्रम समाप्ति का कारण बनता है, कोई सफाई नहीं की जाती है। यह कहा जाना चाहिए कि क्या कार्यक्रम वास्तव में, वास्तव में अप्रत्याशित तरीके से समाप्त हो गया है। यह असामान्य समाप्ति के बारे में ओएस के सिवा कुछ नहीं करेगा। कुछ सिस्टम इस मामले में एक कोर डंप करते हैं।
std::terminateकॉल std::terminate_handlerजो कहता है std::abortडिफ़ॉल्ट रूप से।
main()उपयोग वापसी, कार्यों में एक उचित वापसी मान का उपयोग करें या एक उचित अपवाद फेंक देते हैं। उपयोग न करेंexit()!