बाहर निकलने () और गर्भपात () के बीच अंतर क्या है?


130

सी और सी ++ में, क्या बीच का अंतर है exit()और abort()? मैं एक त्रुटि (अपवाद नहीं) के बाद अपने कार्यक्रम को समाप्त करने की कोशिश कर रहा हूं।

जवाबों:


116

abort()बिना कॉल किए हुए फंक्शंस के लिए अपने प्रोग्राम से बाहर निकलता है atexit(), और पहली बार ऑब्जेक्ट्स डिस्ट्रक्टर्स को कॉल किए बिना। exit()अपने कार्यक्रम से बाहर निकलने से पहले दोनों करता है। हालांकि यह स्वचालित वस्तुओं के लिए विनाशकारी नहीं कहता है। इसलिए

A a;
void test() { 
    static A b;
    A c;
    exit(0);
}

विनाश करेगा aऔर bठीक से, लेकिन के विनाशकों को नहीं बुलाएगा cabort()न तो वस्तुओं को नष्ट करने वालों को नहीं बुलाएगा। जैसा कि यह दुर्भाग्यपूर्ण है, सी ++ मानक एक वैकल्पिक तंत्र का वर्णन करता है जो ठीक से समाप्ति सुनिश्चित करता है:

स्वचालित भंडारण अवधि वाली वस्तुएं एक कार्यक्रम में नष्ट हो जाती हैं, जिनके कार्य main()में कोई स्वचालित वस्तु नहीं होती है और कॉल को निष्पादित करती है exit()main()एक अपवाद को फेंककर नियंत्रण को सीधे ऐसे स्थानांतरित किया जा सकता है जो अंदर पकड़ा गया हो main()

struct exit_exception { 
   int c; 
   exit_exception(int c):c(c) { } 
};

int main() {
    try {
        // put all code in here
    } catch(exit_exception& e) {
        exit(e.c);
    }
}

कॉल exit()करने के throw exit_exception(exit_code);बजाय उस कोड को व्यवस्थित करें ।


2
+1 क्योंकि, ब्रायन आर। बॉडी अच्छा था, आपने एबॉर्ट / एग्जिट (जिसे स्टैक ऑब्जेक्ट्स का डिस्ट्रक्टर नहीं कहा जाता है) की समस्या को उठाया, और आरएआई-गहन सी ++ प्रक्रिया के लिए विकल्प की पेशकश की।
पियरसबल

मैं एक कार्यक्रम छोड़ने के लिए एक रास्ता देख रहा था बिना डॉटर को बुलाए और आपका जवाब सिर्फ वही है जो मैं देख रहा था! धन्यवाद
acemtp

यह पूरी तरह से सही है, अगर यह वास्तव में मायने रखता है कि आपके स्वचालित ऑब्जेक्ट डिस्ट्रक्टर्स को :-) नहीं कहा जाता है
क्रिस हुआंग-लीवर

मेरे ज्ञान के लिए, बाहर निकलने और गर्भपात के बीच एक और अंतर यह होगा कि गर्भपात (ऑपरेटिंग सिस्टम कॉन्फ़िगरेशन के आधार पर) एक कोर डंप की पीढ़ी को जन्म दे सकता है।
डिर्क हेरमैन

33

abort एक SIGABRT सिग्नल भेजता है, बाहर निकलने से सामान्य सफाई करने वाले एप्लिकेशन बंद हो जाते हैं।

आप चाहे तो एबॉर्ट सिग्नल को संभाल सकते हैं, लेकिन डिफॉल्ट व्यवहार एप्लिकेशन को बंद करने के साथ-साथ एरर कोड भी होता है।

गर्भपात आपके स्थिर और वैश्विक सदस्यों के ऑब्जेक्ट विनाश का प्रदर्शन नहीं करेगा, लेकिन बाहर निकल जाएगा।

बेशक, जब एप्लिकेशन पूरी तरह से बंद हो जाता है, तो ऑपरेटिंग सिस्टम किसी भी अनमोल मेमोरी और अन्य संसाधनों को मुक्त कर देगा।

दोनों गर्भपात और निकास कार्यक्रम समाप्ति में (यह मानते हुए कि आपने डिफ़ॉल्ट व्यवहार को ओवरराइड नहीं किया है), वापसी कोड आपके आवेदन शुरू करने वाली मूल प्रक्रिया में वापस आ जाएगा।

निम्नलिखित उदाहरण देखें:

SomeClassType someobject;

void myProgramIsTerminating1(void)
{
  cout<<"exit function 1"<<endl;
}

void myProgramIsTerminating2(void)
{
  cout<<"exit function 2"<<endl;
}

int main(int argc, char**argv)
{
  atexit (myProgramIsTerminating1);
  atexit (myProgramIsTerminating2);
  //abort();
  return 0;
}

टिप्पणियाँ:

  • यदि गर्भपात को अनियोजित किया जाता है: कुछ भी मुद्रित नहीं किया जाता है और किसी-किसी के विनाशकर्ता को नहीं बुलाया जाएगा।

  • यदि गर्भपात की टिप्पणी ऊपर की तरह की गई है: किसी-किसी को विध्वंसक कहा जाएगा तो आपको निम्न आउटपुट मिलेंगे:

निकास समारोह 2
निकास समारोह 1


यहां, इसे एग्जिट फंक्शन 2 THEN एग्जिट फंक्शन 1. gcc 4, Linux 2.6 कहा जाता है।
स्ट्रैजर

1
एटैक्सिट के लिए मैन पेज कहता है: "फ़ंक्शंस [एटेक्सिट का उपयोग करके पंजीकृत] को रिवर्स ऑर्डर में बुलाया जाता है; कोई तर्क पारित नहीं किया जाता है।"
स्ट्रैजर

@strager सही है, atexit द्वारा पंजीकृत कार्यों को उल्टे क्रम में बुलाया जाना चाहिए जब या तो निकास कहा जाता है या मुख्य रिटर्न।
राबर्ट गैंबल

एक परीक्षण में भाग लिया और यह प्रतीत होता है कि वैश्विक उदाहरणों के लिए विनाशकारी सभी एटेक्सिट कॉलबैक के बाद कहा जाता है।
स्ट्रैजर

+1 लोगों को यह याद दिलाने के लिए कि ओएस अंततः एक आवंटित () कॉल के बाद भी सभी आवंटित संसाधनों को मुक्त कर देगा।
फिंगोल्फिन

10

जब प्रोग्राम कॉल होता है तो निम्न चीजें होती हैं exit():

  • फ़ंक्शन द्वारा पंजीकृत atexitकार्य निष्पादित किए जाते हैं
  • सभी खुली धाराएँ प्रवाहित और बंद हो जाती हैं, tmpfileइनके द्वारा बनाई गई फाइलें हटा दी जाती हैं
  • कार्यक्रम मेजबान के लिए निर्दिष्ट निकास कोड के साथ समाप्त होता है

abort() फ़ंक्शन भेजता है SIGABRTयह पकड़ा नहीं है, तो कार्यक्रम कोई गारंटी नहीं कि खुले धाराओं प्लावित / बंद हो जाती हैं या के माध्यम से बनाया अस्थायी फ़ाइलों को उस के साथ समाप्त होता है, वर्तमान प्रक्रिया के लिए संकेत tmpfileनिकाल दिए जाते हैं, atexitपंजीकृत कार्यों कहा जाता है नहीं कर रहे हैं, और एक गैर मेजबान के लिए शून्य निकास स्थिति वापस आ गई है।


हम्म। मानक कहता है कि प्रोग्राम केवल तभी समाप्त नहीं होता है जब सिग्नल हैंडलर "वापस नहीं आता"। आप सी के साथ काफी अच्छी तरह से हैं। क्या आप किसी ऐसे परिदृश्य की कल्पना कर सकते हैं जो इसे बिना वापस लिए सामान्य निष्पादन जारी रखने की अनुमति देगा? मैं longjmp की कल्पना करता हूं, लेकिन मुझे यकीन नहीं है कि यह सिग्नल हैंडलर में कैसे व्यवहार करता है।
जोहान्स शाउब - ३

सामान्य तौर पर, सिग्नल हैंडलर से लॉन्गजम्प को अपरिभाषित किया जाता है, लेकिन इसके लिए एक विशेष मामला है जब सिग्नल को बढ़ाने / एबोर्ट के साथ उत्पन्न किया गया था, तो मुझे लगता है कि यह सैद्धांतिक रूप से संभव होगा, हालांकि मुझे नहीं लगता कि मैंने कभी ऐसा किया है। अब मैं इसे आजमाने जा रहा हूं;)
रॉबर्ट गैंबल

1
यह काम करने लगता है (300 वर्ण सीमा के कारण कई पदों में टूट गया): #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <setjmp .h> वाष्पशील sig_atomic_t do_abort = 1; jmp_buf env; void abort_handler (int i) {do_abort = 0; longjmp (env, 1);}
रॉबर्ट गैम्बल

int main (शून्य) {setjmp (env); डालता है ("सेटजम्प पर"); अगर (do_abort) {संकेत (SIGABRT, abort_handler); डालता है ("कॉलिंग एबोर्ट"); बीच में बंद करें (); } डालता है ("गर्भपात नहीं किया!"); वापसी 0; }
रॉबर्ट गैंबल

उबंटू 7.04 पर यह प्रिंट: सेटजम्प में कॉलिंग एबॉर्ट में सेटजम्प में गर्भपात नहीं हुआ!
रॉबर्ट गैंबल

5

बाहर निकलने से () मैनुअल पेज:

निकास () फ़ंक्शन सामान्य प्रक्रिया समाप्ति का कारण बनता है और स्थिति और 0377 का मान माता-पिता को वापस कर दिया जाता है।

गर्भपात () मैनुअल पेज से:

गर्भपात () पहले SIGABRT सिग्नल को अनब्लॉक करता है, और फिर कॉलिंग प्रक्रिया के लिए उस सिग्नल को उठाता है। यह प्रक्रिया की असामान्य समाप्ति के परिणामस्वरूप होता है जब तक कि SIGABRT सिग्नल पकड़ा नहीं जाता है और सिग्नल हैंडलर वापस नहीं आता है।


4

abortSIGABRTसंकेत भेजता है । abortकॉलर को वापस नहीं करता है। SIGABRTसिग्नल के लिए डिफ़ॉल्ट हैंडलर एप्लिकेशन को बंद कर देता है। stdioफ़ाइल धाराओं को फ़्लश किया जाता है, फिर बंद कर दिया जाता है। C ++ वर्ग के उदाहरणों के लिए विनाशकारी नहीं हैं, हालांकि (इस पर निश्चित नहीं हैं - शायद परिणाम अपरिभाषित हैं)।

exitअपने स्वयं के कॉलबैक हैं, जिनके साथ सेट किया गया है atexit। यदि कॉलबैक निर्दिष्ट किए जाते हैं (या केवल एक), तो उन्हें अपने पंजीकरण क्रम के क्रम में (स्टैक की तरह) कहा जाता है, फिर प्रोग्राम बाहर निकलता है। साथ abort, exitकॉल करने वाले के पास वापस नहीं जाता है। stdioफ़ाइल धाराओं को फ़्लश किया जाता है, फिर बंद कर दिया जाता है। इसके अलावा, C ++ वर्ग के उदाहरणों के लिए विध्वंसक कहा जाता है।


बाहर निकलना कई अलग-अलग कॉलबैक फ़ंक्शंस एटैक्सिट के माध्यम से पंजीकृत हो सकता है, जब बाहर निकलने को कॉल किया जाता है सभी कॉलबैक फ़ंक्शन को रिवर्स ऑर्डर में बुलाया जाएगा जिसमें वे पंजीकृत थे।
राबर्ट गैम्बल

@Gamble, निश्चित रूप से, मैंने उल्लेख किया है कि कुछ मिनट पहले @ बॉडी के जवाब के लिए एक टिप्पणी थी। मैं अपना स्वयं का उत्तर संपादित करूँगा कि वह प्रतिबिंबित हो जाए।
स्ट्रगर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.