गर्भपात, समाप्त या बाहर निकलें?


112

उन तीनों के बीच क्या अंतर है, और मैं अपवाद के मामले में कार्यक्रम को कैसे समाप्त करूंगा जो मैं ठीक से नहीं संभाल सकता हूं?


3
यह एक डुप्लिकेट नहीं है, बल्कि, कुछ अच्छे उत्तरों के साथ एक सबसेट है stackoverflow.com/questions/397075/… और इसे C ++ भी टैग किया गया था!
ऐली केसेलमैन

std::abortएक विध्वंसक में एक अपवाद को हल नहीं किया जा सकता है तो उचित है।
डैनियल

1
अंद्रेजstd::terminate के उत्कृष्ट सी ++ ब्लॉग में इन लेखों को देखने के बारे में अधिक जानकारी के लिए : akrzemi1.wordpress.com/2011/09/28/who-calls-stdterminate , akrzemi1.wordpress//
Schneider

जवाबों:


3

मेरी सलाह होगी कि उनमें से किसी का भी इस्तेमाल न करें। इसके बजाय, catchआप जिन अपवादों को संभाल नहीं सकते हैं main()और बस returnवहां से। इसका मतलब है कि आपको गारंटी दी जाती है कि स्टैक अनइंडिंग सही ढंग से होती है और सभी डिस्ट्रक्टर्स कहलाते हैं। दूसरे शब्दों में:

int main() {
    try {
       // your stuff
    }
    catch( ... ) {
       return 1;    // or whatever
    }
}

8
@ नील: मूल रूप से सहमत हैं, लेकिन अपवाद है कि कार्यक्रम को संभाल नहीं सकते रिपोर्ट और पुनर्विचार किया जाना चाहिए। ऐप को क्रैश होने दें।
जॉन डिबलिंग

13
यह सुनिश्चित करने के लिए कि स्टैक अनइंड्स आपको हमेशा मुख्य में पकड़ना चाहिए। लेकिन मैं फिर से कैच छोड़ दूंगा। जैसा कि कुछ ओएस में डिबगिंग संकलित करने के लिए स्वचालित रूप से डिबगिंग इन्फ्रास्ट्रक्चर को आमंत्रित करने की क्षमता है।
मार्टिन यॉर्क

5
शीर्ष-स्तरीय हैंडलर द्वारा पकड़े गए अपवाद भी एक सिस्टम रिपोर्टिंग सुविधा को लागू कर सकते हैं जो प्रक्रिया को डंप करता है और डेवलपर्स के ध्यान के लिए अपवाद रिपोर्ट अपलोड करता है, जैसे विंडोज त्रुटि रिपोर्टिंग, मैक ओएस एक्स त्रुटि रिपोर्ट और आईफोन एप्लिकेशन त्रुटि लॉग।
JBRWilkinson

6
@ जो कारण मेरे लिए आश्चर्य की बात है, वह यह है कि, हालांकि यह सही मायने में प्रकाश में है कि अपवादों को वास्तव में कैसे लागू किया जाता है, यह अमूर्त को तोड़ता है कि एक अपवाद "स्टैक को प्रचारित करता है" जब तक कि एक उपयुक्त हैंडलर नहीं मिला (या समाप्त नहीं हुआ) बुलाया)। और टपका हुआ अमूर्त, जबकि अक्सर अपरिहार्य होता है, आवश्यक रूप से आश्चर्य की बात है जब सामना किया जाता है।
टायलर मैकहेनरी

11
-1 क्योंकि यह आधे सवाल का जवाब नहीं देता है। "[एबॉर्ट, टर्मिनेट या एक्जिट?] के बीच अंतर क्या है?" यह एक बेहतर जवाब है: stackoverflow.com/a/397081/353094 इसके अलावा stackoverflow.com/a/2820407/353094 एक शानदार जवाब है।
leetNightshade

149
  • गर्भपात कार्यक्रम के लिए "असामान्य" अंत इंगित करता है, और पोसिक्स सिग्नल SIGABRT को उठाता है, जिसका अर्थ है कि उस सिग्नल के लिए आपके द्वारा पंजीकृत किसी भी हैंडलर को आमंत्रित किया जाएगा, हालांकि कार्यक्रम अभी भी किसी भी मामले में afterwords को समाप्त करेगा। आमतौर पर आप abortअनपेक्षित त्रुटि मामले से बाहर निकलने के लिए सी प्रोग्राम में उपयोग करते हैं , जहां प्रोग्राम खराब होने या नेटवर्क विफलता जैसी किसी चीज के बजाय प्रोग्राम में बग होने की संभावना है। उदाहरण के लिए, abortयदि आप डेटा संरचना में NULL पॉइंटर होने का पता लगा सकते हैं, जब तार्किक रूप से ऐसा कभी नहीं होना चाहिए।

  • निकास कार्यक्रम के लिए एक "सामान्य" अंत इंगित करता है, हालांकि यह अभी भी एक विफलता (लेकिन बग नहीं) का संकेत दे सकता है। दूसरे शब्दों में, आप exitएक त्रुटि कोड के साथ हो सकते हैं यदि उपयोगकर्ता ने इनपुट दिया है जिसे पार्स नहीं किया जा सकता है, या एक फ़ाइल नहीं पढ़ी जा सकती है। 0 से बाहर निकलने का कोड सफलता दर्शाता है। exitवैकल्पिक रूप से प्रोग्राम को समाप्त करने से पहले हैंडलर को भी बुलाता है। इन कार्यों atexitऔर on_exitकार्यों के साथ पंजीकृत हैं ।

  • std :: समाप्ति एक स्वचालित रूप से एक सी + + कार्यक्रम में कहा जाता है जब एक अखंड अपवाद है। यह अनिवार्य रूप से C ++ के बराबर है abort, यह मानते हुए कि आप अपवाद फेंकने के माध्यम से अपनी सभी असाधारण त्रुटियों की रिपोर्ट कर रहे हैं। यह std::set_terminateफ़ंक्शन द्वारा सेट किए गए हैंडलर को कॉल करता है, जो डिफ़ॉल्ट रूप से कॉल करता है abort

C ++ में, आप आमतौर पर कॉलिंग abortया exitत्रुटि से बचना चाहते हैं , क्योंकि आप एक अपवाद को फेंकना बेहतर समझते हैं और कोड को आगे कॉल स्टैक तक तय करते हैं कि कार्यक्रम उचित है या नहीं। आप exitसफलता के लिए उपयोग करते हैं या नहीं, यह परिस्थिति का विषय है - चाहे या न हो, लेकिन वापसी के बयान के अलावा कार्यक्रम को कहीं और समाप्त कर देना चाहिए main

std::terminateC ++ में भी एक अंतिम-खाई त्रुटि रिपोर्टिंग उपकरण माना जाना चाहिए। इसके साथ समस्या std::terminateयह है कि समाप्त हैंडलर के पास उस अपवाद तक पहुंच नहीं है, जो अखंड हो गया है, इसलिए यह बताने का कोई तरीका नहीं है कि यह क्या था। आप आमतौर पर एक try { } catch (std::exception& ex) { }ब्लॉक में मुख्य की संपूर्णता को लपेटकर बहुत बेहतर होते हैं । कम से कम तब आप उन अपवादों के बारे में अधिक जानकारी दर्ज कर सकते हैं, जो इससे प्राप्त हुए हैं std::exception(हालांकि निश्चित रूप से ऐसे अपवाद जो std::exceptionअभी भी नहीं निकले हैं, वे समाप्त हो जाएंगे)।

के शरीर रैपिंग mainमें try { } catch(...) { }ज्यादा हैंडलर समाप्त कर दें, क्योंकि फिर आप प्रश्न में अपवाद के लिए कोई उपयोग कर सकते है की स्थापना की तुलना में बेहतर नहीं है। संपादित करें: प्रति नील बटरवर्थ के जवाब में, इसमें एक लाभ यह है कि इस मामले में स्टैक अनजाना है, जो कि (कुछ आश्चर्यजनक रूप से) एक अखंड अपवाद के लिए सही नहीं है।


10
क्या आप इस उत्तर को C ++ 11 जानकारी के साथ अपडेट कर सकते हैं? ऐसा लगता है कि अब कैच (...) और टर्मिनेट हैंडलर में अपवाद प्राप्त करने के तरीके हैं।
16:02 को

1
C ++ में समाप्त हैंडलर करता है के माध्यम से अपवाद की पहुंच है std::current_exception()। यहाँ देखें उदाहरण: akrzemi1.wordpress.com/2011/10/05/use-stdterminate
anorm

इससे कोई फर्क नहीं पड़ता कि आप वर्तमान अपवाद प्राप्त कर सकते हैं, क्योंकि आप इसका निरीक्षण नहीं कर सकते। आप बस फिर से इसे फेंक सकते हैं।
सीटब्लकपीपी


16

std :: abort और std :: exit (और अधिक: std :: _ Exit, std :: quick_exit) केवल निचले स्तर के कार्य हैं। आप उनका उपयोग प्रोग्राम को यह बताने के लिए करते हैं कि आप इसे वास्तव में क्या करना चाहते हैं: कॉल करने के लिए क्या विध्वंसक (और यदि), कॉल करने के लिए अन्य क्लीन-अप फ़ंक्शन क्या हैं, वापस लौटने के लिए क्या मूल्य है, आदि।

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

विशेष रूप से, ध्यान दें कि std :: terminate को संदर्भों में एक अपवाद हैंडलर माना जाता है, जहाँ std :: terminate को एक फेंके गए अपवाद के कारण कहा जाता है, जिसे संभाला नहीं जा सकता था, और आप जांच कर सकते हैं कि अपवाद क्या था और इसे ++ का उपयोग करके निरीक्षण करें 11 std :: rethrow_exception और std :: current_exception का उपयोग करते हुए। यह सब मेरी पोस्ट में है


क्या सिस्टम सिग्नल की वजह से केस प्रोग्राम टर्मिनेट में क्लीन हैंडलर होना उचित है? उदाहरण के लिए, अमान्य मेमोरी एक्सेस SIGSEGV सिग्नल की पीढ़ी की ओर जाता है। इस मामले में, क्या यह अच्छा है कि कार्यक्रम को समाप्त कर दें और कोर फाइल को साफ करने के लिए या सिग्नल हैंडलर को पंजीकृत करें ?? क्या एसटीडी को समाप्त करते समय सफाई करने की तुलना में सिस्टम सिग्नल को संभालने के दौरान सफाई करने की कोई चिंता है?
कार्तिक त्रिविक्रम

12

quick_exit () !

यदि आपका कार्यक्रम बहु-थ्रेडेड है, तो कॉल करने exit()से सबसे अधिक दुर्घटना होने की संभावना होगी क्योंकि वैश्विक / स्थिर std::threadवस्तुओं को उनके धागे से बाहर निकाले बिना नष्ट करने का प्रयास किया जाएगा।

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

नोट: quick_exit () संस्करण 2015 तक MSVC ++ द्वारा समर्थित नहीं किया गया है


4
  • टर्मिनेट आपको यह दर्ज करने की संभावना छोड़ देता है कि जब यह कहा जाता है तो क्या होगा। अन्य दो में से एक होना चाहिए।
  • निकास एक सामान्य निकास है जो निकास स्थिति को निर्दिष्ट करने की अनुमति देता है। At_exit () द्वारा पंजीकृत हैंडलर चलाए जाते हैं
  • गर्भपात एक असामान्य निकास है। केवल एक चीज जो भागा है वह है SIGABRT के लिए सिग्नल हैंडलर।

4
  • समाप्त () स्वचालित रूप से कहा जाता है जब एक अपवाद होता है जिसे संभाला नहीं जा सकता है। डिफ़ॉल्ट रूप से, समाप्त () कॉल गर्भपात ()। आप set_terminate () फ़ंक्शन के साथ एक कस्टम हैंडल सेट कर सकते हैं।

    abort () SIGABRT सिग्नल भेजता है।

    बाहर निकलना () जरूरी नहीं कि बुरी चीज हो। यह सफलतापूर्वक एप्लिकेशन से बाहर निकलता है, और एलआईएफओ ऑर्डर में एटैक्सिट () फ़ंक्शन को कॉल करता है। मैं इसे सामान्य तौर पर C ++ अनुप्रयोगों में नहीं देखता, हालांकि, मैं इसे कई यूनिक्स आधारित अनुप्रयोगों में देखता हूं जहां यह अंत में एक निकास कोड भेजता है। आमतौर पर एक निकास (0) एप्लिकेशन के एक सफल रन को इंगित करता है।


8
असफल! यूनिक्स और डॉस दोनों में, बाहर निकलना (0) सफलता को इंगित करता है और बाहर निकलने के लिए पारित कोई अन्य मूल्य () विफलता को इंगित करता है, न कि दूसरे तरीके से!
रिचर्ड बैरेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.