वापसी विवरण बनाम निकास () मुख्य में ()


197

क्या मुझे exit()केवल returnबयानों का उपयोग करना चाहिए main()? व्यक्तिगत रूप से मैं returnकथनों का पक्ष लेता हूं क्योंकि मुझे लगता है कि यह किसी अन्य फ़ंक्शन को पढ़ने जैसा है और जब मैं कोड पढ़ रहा हूं तो प्रवाह नियंत्रण (मेरी राय में) सुचारू है। और यहां तक ​​कि अगर मैं main()फंक्शन को रिफ्लेक्टर करना चाहता हूं , तो returnलगता है कि यह एक बेहतर विकल्प है exit()

क्या exit()कुछ विशेष returnनहीं करता है?

जवाबों:


277

वास्तव में, वहाँ है एक अंतर है, लेकिन यह सूक्ष्म है। C ++ के लिए इसके अधिक निहितार्थ हैं, लेकिन अंतर महत्वपूर्ण हैं।

जब मैं returnअंदर main()जाता हूं, तो विध्वंसक को मेरी स्थानीय रूप से बिखरी वस्तुओं के लिए बुलाया जाएगा। अगर मैं फोन करता हूं exit(), तो मेरी स्थानीय रूप से बिखरी हुई वस्तुओं के लिए कोई विध्वंसक नहीं कहा जाएगा! फिर से पढ़ें। exit() वापस नहीं आता है । इसका मतलब है कि एक बार जब मैं इसे कॉल करता हूं, तो "कोई बैकसीज़" नहीं होता है। आपके द्वारा उस फ़ंक्शन में बनाई गई कोई भी वस्तु नष्ट नहीं होगी। अक्सर इसका कोई निहितार्थ नहीं होता है, लेकिन कभी-कभी यह बंद फाइलों की तरह होता है (निश्चित रूप से आप चाहते हैं कि आपका सारा डेटा डिस्क में प्रवाहित हो जाए)।

ध्यान दें कि staticयदि आप कॉल करते हैं तो भी वस्तुओं को साफ किया जाएगा exit()। अंत में, ध्यान दें कि यदि आप उपयोग करते हैं abort(), तो कोई भी वस्तु नष्ट नहीं होगी। अर्थात्, कोई वैश्विक वस्तु, कोई स्थैतिक वस्तु और कोई स्थानीय वस्तु उनके विध्वंसक नहीं होंगे।

वापसी पर बाहर निकलने के पक्ष में सावधानी के साथ आगे बढ़ें।

http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a


1
गर्भपात () त्रुटि स्थिति (गैर-शून्य निकास कोड) के साथ बाहर निकलता है और यहां तक ​​कि कोर भी हो सकता है। यदि आपको स्थिर विध्वंसक कॉलिंग w / o से बाहर निकलने की आवश्यकता है, तो _exit का उपयोग करें।

7
@ माइक: सी लाइब्रेरी फ़ाइल बफ़र्स और C ++ फ़ाइल स्ट्रीम ऑब्जेक्ट के बीच अंतर है। बाहर निकलना () - सी लाइब्रेरी का हिस्सा होना - पूर्व के साथ समन्वय करने और फ्लश करने के लिए डिज़ाइन किया गया था, लेकिन बाद को बायपास कर सकता है: यहां तक ​​कि मानक सी ++ फ़्लोस्ट्रीम सामग्री डिस्क पर फ्लश नहीं की जाती है (इसे आज़माएं - मैंने किया, यह w / Linux / w विफल रहता है) जीसीसी), और स्पष्ट रूप से उपयोगकर्ता-परिभाषित प्रकार जो आई / ओ को बफ़र करते हैं, उनसे उम्मीद नहीं की जा सकती है।
टोनी डेलरॉय

9
नोट: कथन: कोई विध्वंसक मेरी स्थानीय रूप से बिखरी हुई वस्तुओं के लिए नहीं बुलाया जाएगा! C ++ 11 के लिए अब सच नहीं है: - थ्रेड स्टोरेज की अवधि के साथ वर्तमान थ्रेड से जुड़ी वस्तुएं नष्ट हो जाती हैं (C ++ 11 केवल)। cplusplus.com/reference/cstdlib/exit
Ilendir

7
इसका अर्थ है, thread_localवस्तुओं के विध्वंसक कहलाएंगे। अन्य स्थानीय वस्तुओं के लिए विनाशकों को अभी भी नहीं कहा जाता है। ideone.com/Y6Dh3f
HolyBlackCat

3
BTW, और सिर्फ पांडित्यपूर्ण होना और क्योंकि यह उत्तर अभी भी C का उपयोग करने वाले पाठकों के लिए भ्रामक हो सकता है: C के लिए exit()फ़ाइलें साफ करने के बारे में समस्या वास्तव में गलत है। केवल समय डेटा को फ्लश नहीं किया जा सकता है, विपरीत स्थिति में है: यानी यदि कोई उपयोग करता returnहै main()और किसी ने एक बफर के साथ setbuf()या उसके setvbuf()साथ स्वचालित भंडारण के रूप में घोषित किया है main()(जैसा कि नीचे आर के जवाब में चर्चा की गई है)। यह वास्तव में बहुत बुरा है, इस प्रश्न को C और C ++ (और कोडिंग-स्टाइल - यह शैली का मुद्दा नहीं है) दोनों के साथ टैग किया गया है।)
ग्रेग ए। वुड्स

25

एक और अंतर: exitएक मानक लाइब्रेरी फ़ंक्शन है इसलिए आपको हेडर और मानक लाइब्रेरी के साथ लिंक शामिल करने की आवश्यकता है। समझाने के लिए (C ++ में), यह एक वैध कार्यक्रम है:

int main() { return 0; }

लेकिन उपयोग करने के लिए exitआपको एक आवश्यकता होगी:

#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }

इसके अलावा यह एक अतिरिक्त धारणा जोड़ता है: कि कॉलिंग exitसे mainशून्य वापस करने के समान दुष्प्रभाव होते हैं। जैसा कि दूसरों ने बताया है, यह इस बात पर निर्भर करता है कि आप किस तरह का निष्पादन योग्य निर्माण कर रहे हैं (यानी, कौन बुला रहा है main)। क्या आप किसी ऐप को सी-रनटाइम का उपयोग करते हैं? एक माया प्लगइन? एक विंडोज सेवा? एक ड्राइवर? प्रत्येक मामले को देखने के लिए अनुसंधान की आवश्यकता होगी कि क्या exitयह समकक्ष है return। IMHO का उपयोग exitकरते हुए जब आप वास्तव में इसका मतलब return सिर्फ कोड को अधिक भ्रमित करते हैं। OTOH, यदि आप वास्तव में मतलब रखते हैं exit , तो हर तरह से इसका उपयोग करें।


16

पसंद करने का कम से कम एक कारण है exit: यदि आपका कोई भी atexitहैंडलर स्वचालित-स्टोरेज-अवधि डेटा को संदर्भित करता है main, या यदि आपने किसी मानक स्ट्रीम में किसी एक को उपयोग करने के लिए उपयोग किया है setvbufया setbufकरने के लिए असाइन किया है main, तो mainउत्पादन से लौट रहा है अपरिभाषित व्यवहार, लेकिन कॉलिंग exitमान्य है।

एक अन्य संभावित उपयोग (आमतौर पर खिलौना कार्यक्रमों के लिए आरक्षित है, हालांकि) के पुनरावर्ती चालान के साथ एक कार्यक्रम से बाहर निकलना है main


1
@ कोई खास बात नहीं है main()- यह किसी भी अन्य की तरह एक समारोह है। दूसरी ओर चूंकि इसका मानक में विशेष उल्लेख है, इसलिए मानक को इस बारे में काफी सावधानी बरतनी चाहिए कि यह कैसे परिभाषित करता है main()और इसके पास की चीजें और प्रिय। हालांकि अंत में हालांकि मानक (और नहीं करना चाहिए ) को संचयकों के लिए ऑटो स्टोरेज के बारे में कुछ विशेष करने की आवश्यकता नहीं है main()। कृपया अपने टिप्पणी में संदर्भित पैराग्राफ के नीचे फुटनोट # 11 पढ़ने का ध्यान रखें।
ग्रेग ए। वुड्स

1
@ ग्रेग.वूड्स दिलचस्प। ऐसा लगता है कि कुछ जानकारीपूर्ण पाठ के विरोधाभास में कुछ प्रामाणिक पाठ है। आईएसओ / आईईसी निर्देशों के अनुसार , मानक संदर्भ को "अपरिहार्य" माना जाता है, जहां-जैसा कि सूचनात्मक को केवल पूरक माना जाता है ... इसके अलावा, एक आवश्यकता को व्यक्त करने के लिए "इच्छा" शब्द का उपयोग अमान्य है; उपरोक्त दस्तावेज (अनुबंध एच) के अनुसार। सारांश में, सूचनात्मक पाठ सबसे निश्चित रूप से अमान्य है।
ऑटिस्टिक

2
@ सेब: इरादा स्पष्ट रूप से स्वचालित भंडारण के व्यवहार पर आवश्यकताओं को ओवरराइड नहीं करना है और स्पष्ट रूप से इसे स्पष्ट करने के लिए फुटनोट लिखा गया था। हां, सी मानक में खराब, खराब स्थिति है। जिसने भी इसे पढ़ा है वह यह जानता है। हम यह भी जानते हैं कि समिति आम तौर पर इस तरह के मुद्दों को ठीक नहीं करती है क्योंकि इरादा पहले से ही स्पष्ट है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

1
@ सीब: यह साबित करने के लिए कि आप सही हैं बहस या अदालत का मामला नहीं है। लक्ष्य को स्पष्ट समझ प्राप्त होनी चाहिए कि वास्तविक सी भाषा (जैसा कि इरादा है और जैसा कि कार्यान्वित किया गया है) है, और उन उत्तरों में व्यक्त करना जो पाठकों के लिए उपयोगी हैं। मानदंड पाठ सूक्ष्म रूप से गलत है (यह व्यक्त करने के इरादे के विपरीत) एक तरह से जो कि आवश्यक रूप से फ़ुटनोट द्वारा तय किया गया है। यदि आप इससे खुश नहीं हैं, तो एक दोष रिपोर्ट प्रस्तुत करें, लेकिन उत्तर की अपेक्षा न करें। यह है कि WG14 कैसे रोल करता है ...
R .. GitHub STOP हेल्पिंग ICE

3
@ सिब: आपको लगता है कि सी भाषा को मानक के प्राकृतिक-भाषा के पाठ की व्याख्या करके समझा जा सकता है जैसे कि यह पूरी तरह कठोर हो। यह बस संभव नहीं है। विनिर्देश में गलतियाँ हैं, और WG14 अपना समय पुनर्लेखन सामान बर्बाद नहीं करता है जब एक साधारण फुटनोट स्पष्ट करता है कि वे पहले से ही जानते हैं कि उन्होंने एक गलती की है लेकिन पाठक इसे समझ सकता है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

5

मैं हमेशा उपयोग करता हूं returnक्योंकि मानक प्रोटोटाइप का main()कहना है कि यह रिटर्न ए int

उस ने कहा, मानकों के कुछ संस्करण mainविशेष उपचार देते हैं और यह मानते हैं कि यदि कोई स्पष्ट returnविवरण नहीं है तो यह 0 देता है । निम्नलिखित कोड दिया गया है:

int foo() {}
int main(int argc, char *argv[]) {}

G ++ केवल के लिए एक चेतावनी उत्पन्न करता है foo()और इससे लापता रिटर्न को अनदेखा करता है main:

% g++ -Wall -c foo.cc
foo.cc: In function int foo()’:
foo.cc:1: warning: control reaches end of non-void function

मैं C के बारे में नहीं जानता, लेकिन C ++ मानक यह निर्दिष्ट करता है कि यदि आप मुख्य में कोई मान नहीं लौटाते हैं, तो यह मान लिया जाता है कि 0.
जेसन बेकर

ऐसा लगता है जैसे C99 एक ही है: faq.cprogramming.com/cgi-bin/…
जेसन बेकर

2
C99 और C ++ वापसी 0 अगर कोई रिटर्न स्टेटमेंट नहीं है, तो C90 नहीं।
d0k

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

@ ग्रेग.हूड्स आपकी राय है, लेकिन शायद ही एक डाउन-वोट की योग्यता है! मैंने जो ऊपर लिखा है वह पूरी तरह से मानक के अनुरूप है , जबकि आपका तर्क सिर्फ शब्दार्थ है।
अलनीतक

5

मैं दृढ़ता से दूसरी आर द्वारा टिप्पणी क्रम में स्वत: भंडारण होने से बचने के लिए बाहर निकलें () का उपयोग कर के बारे में main()कार्यक्रम वास्तव में समाप्त होने से पहले फिर से दावा। रिटर्न में डायनेमिक स्टोरेज के गायब होने के बाद से कॉल करने के लिए एक return X;स्टेटमेंट main()ठीक-ठीक नहीं है, लेकिन कॉल के बदले कॉल करने पर यह गायब नहीं होता है।exit(X);main()main()exit()

इसके अलावा, C या किसी भी C- जैसी भाषा में, एक returnकथन पाठक को दृढ़ता से संकेत देता है कि निष्पादन कॉलिंग फ़ंक्शन में जारी रहेगा, और जबकि निष्पादन की यह निरंतरता तकनीकी रूप से सही है यदि आप सी स्टार्टअप दिनचर्या को गिनते हैं जो आपके main()फ़ंक्शन को कहते हैं, तो यह नहीं है वास्तव में क्या आप मतलब जब आप प्रक्रिया समाप्त करने के लिए मतलब है।

सब के बाद, को छोड़कर यदि आप किसी अन्य समारोह के भीतर से अपने कार्यक्रम समाप्त करना चाहते हैं main()तो आप चाहिए फोन exit()main()साथ ही लगातार ऐसा करने से आपका कोड बहुत अधिक पठनीय हो जाता है, और इससे किसी को भी आपके कोड को री-फैक्टर करना बहुत आसान हो जाता है; यानी main()किसी अन्य फ़ंक्शन से कॉपी किए गए कोड में आकस्मिक returnबयानों के कारण दुर्व्यवहार नहीं होगा जो कॉल होना चाहिए था exit()

इसलिए, इन सभी बिंदुओं को एक साथ मिलाकर निष्कर्ष निकाला गया है कि कार्यक्रम को समाप्त करने के लिए एक बयान का उपयोग करने के लिए कम से कम सी के लिए यह एक बुरी आदतreturn है main()


आपको सी मानक के 5.1.2.2.3p1 दिलचस्प मिल सकते हैं ...
ऑटिस्टिक

यह उत्तर सी कार्यक्रमों के लिए सावधानीपूर्वक विचार करने के लायक है, जैसा कि उत्तर में प्रासंगिक रूप से इंगित किया गया है। सी ++ के साथ उपयोग के लिए, पहले से उल्लेख किए गए सभी के खिलाफ सावधानी से तौला जाना चाहिए। सी के लिए ++, मैं से बचने के लिए सुझाव है कि exit()सामान्य रूप में, लेकिन यह प्रयोग कर एक अगर ऐसा throwया abort()विकल्प एक विशिष्ट संदर्भ में काम नहीं करते। लेकिन विशेष रूप से exit()मुख्य में से बचें , और विशिष्ट अभ्यास के बजाय मुख्य में वापसी का उपयोग करें।
एलयज

5

क्या निकास () कुछ विशेष करता है जो 'वापसी' नहीं करता है?

असामान्य प्लेटफार्मों के लिए कुछ संकलक के साथ, exit()अपने तर्क को अपने कार्यक्रम के निकास मूल्य में अनुवाद कर सकते हैं , जबकि वापसी से main()केवल बिना किसी अनुवाद के सीधे मेजबान वातावरण में मान पारित कर सकते हैं।

मानक को इन मामलों में समान व्यवहार की आवश्यकता होती है (विशेष रूप से, यह कहता है कि कुछ-जो कि- intअसंगत है उस मान के साथ main()कॉल करने के बराबर होना चाहिए exit())। समस्या यह है कि विभिन्न ओएस में निकास मूल्यों की व्याख्या करने के लिए अलग-अलग परंपराएं हैं। कई (MANY!) सिस्टम पर, 0 का मतलब सफलता है और कुछ भी विफलता है। लेकिन, कहने पर, VMS, विषम मानों का अर्थ है सफलता और यहां तक ​​कि असफलताओं का अर्थ है। यदि आप 0 से लौटे हैं main(), तो VMS उपयोगकर्ता को एक्सेस उल्लंघन के बारे में एक बुरा संदेश दिखाई देगा। वास्तव में एक एक्सेस उल्लंघन नहीं था - यह केवल मानक संदेश विफलता कोड 0 से जुड़ा था।

तब एएनएसआई ने साथ आकर आशीर्वाद दिया EXIT_SUCCESSऔर उन EXIT_FAILUREतर्कों के रूप में जिन्हें आप पारित कर सकते हैं exit()। मानक यह भी कहता है कि exit(0)पहचान के लिए व्यवहार करना चाहिए exit(EXIT_SUCCESS), इसलिए अधिकांश कार्यान्वयन परिभाषित EXIT_SUCCESSकरते हैं 0

इसलिए, मानक आपको VMS पर एक बाध्यता में रखता है, क्योंकि यह मान 0 होने के लिए विफलता कोड को वापस करने के लिए कोई मानक तरीका नहीं छोड़ता है ।

1990 के दशक के शुरुआती दौर के वैक्स / वीएमएस सी कंपाइलर ने रिटर्न वैल्यू की व्याख्या नहीं की थी main(), इसने मेजबान वातावरण के लिए जो भी मूल्य था वापस कर दिया। लेकिन अगर आपने इसका उपयोग किया exit()है तो मानक के लिए क्या करना होगा: अनुवाद EXIT_SUCCESS(या 0) सफलता कोड में और EXIT_FAILUREसामान्य विफलता कोड में। उपयोग करने के लिए EXIT_SUCCESS, आप के लिए किया था इसे पारित करने के लिए exit(), आप से इसे वापस नहीं कर सकता है main()। मुझे नहीं पता कि उस संकलक के अधिक आधुनिक संस्करणों ने उस व्यवहार को संरक्षित किया है या नहीं।

एक पोर्टेबल सी प्रोग्राम इस तरह दिखता था:

#include <stdio.h>
#include <stdlib.h>

int main() {
  printf("Hello, World!\n");
  exit(EXIT_SUCCESS);  /* to get good return value to OS */
  /*NOTREACHED*/ /* to silence lint warning */
  return 0;  /* to silence compiler warning */
}

एक तरफ: यदि मुझे सही ढंग से याद है, तो बाहर निकलने के मूल्यों के लिए VMS सम्मेलन विषम / से भी अधिक बारीक है। यह वास्तव में एक गंभीर स्तर को सांकेतिक शब्दों में बदलना करने के लिए कम तीन बिट्स की तरह कुछ का उपयोग करता है। आम तौर पर, हालांकि, विषम गंभीरता के स्तर ने सफलता या विविध जानकारी और यहां तक ​​कि त्रुटियों को इंगित किया।


हो सकता है कि कुछ पुराने प्री-एएनएसआई कंपाइलरों returnedने mainअलग-अलग मानों को मानकर पास किया हो exit- लेकिन मानक विशेष रूप से कहते हैं, "यदि mainफ़ंक्शन का रिटर्न प्रकार एक प्रकार के साथ संगत है int, तो mainफ़ंक्शन के लिए प्रारंभिक कॉल से वापसी होती है। exitफ़ंक्शन द्वारा mainअपने तर्क के रूप में दिए गए मान के साथ फ़ंक्शन को कॉल करने के बराबर है "। वह C11 है; C89 / C90 में लगभग एक ही शब्द था।
कीथ थॉम्पसन

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

क्या आपके पास इसके लिए एक प्रशस्ति पत्र है? एक अलग मुद्दा यह है कि क्या किसी भी वर्तमान संकलक में वह विशेष बग है। आपका उत्तर वर्तमान काल में प्रकाशित है।
कीथ थॉम्पसन

यह एक निष्पक्ष आलोचना है। मैंने उस विशिष्ट मामले में गुंजाइश को सीमित करने के लिए शब्द बदल दिया है जिसके बारे में मुझे पता है।
एड्रियन मैक्कार्थी

0

C से लौटने पर उसी मान से mainकॉलिंग exitके समान है।

सी मानक राज्यों की धारा 5.1.2.2.3 :

यदि मुख्य फ़ंक्शन का रिटर्न प्रकार इंट के साथ संगत प्रकार है, तो मुख्य फ़ंक्शन के लिए प्रारंभिक कॉल से एक वापसी इसके फ़ंक्शन के रूप में मुख्य फ़ंक्शन द्वारा दिए गए मान के साथ निकास फ़ंक्शन को कॉल करने के बराबर है ; 11) उस तक पहुंचने वाले} जो मुख्य फ़ंक्शन को समाप्त करता है 0. का मान लौटाता है। यदि रिटर्न प्रकार इंट के साथ संगत नहीं है, तो होस्ट वातावरण में वापस लौटा समाप्ति की स्थिति अनिर्दिष्ट है।

C ++ के नियम अन्य उत्तरों में बताए अनुसार थोड़े अलग हैं।


-1

जब वास्तव में आपके फ़ंक्शन को कई बार कहा जाता है, तो वास्तव में exit(0)और इसके बीच अंतर होता है।return(0)mainmain

निम्नलिखित कार्यक्रम

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  if (argc == 0)
    return(0);
  printf("%d", main(argc - 1, argv));
}

ऐसे दोड़ो

./program 0 0 0 0

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

00000

हालाँकि यह एक:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  if (argc == 0)
    exit(0);
  printf("%d", main(argc - 1, argv));
}

तर्कों की परवाह किए बिना कुछ भी नहीं छापेंगे।

यदि आप सुनिश्चित हैं कि कोई भी कभी भी आपका mainस्पष्ट रूप से कॉल नहीं करेगा , तो यह तकनीकी रूप से सामान्य रूप से एक बड़ा अंतर नहीं है, लेकिन स्पष्ट कोड बनाए रखने के लिए हैexit यह बेहतर लगेगा। यदि आप किसी कारण से कॉल करना चाहते हैं main- तो आपको इसे अपनी आवश्यकताओं के अनुसार समायोजित करना चाहिए।

सी। के बारे में बोलते हुए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.