2011-01-22 14 views
12

सी 99 _Exit फ़ंक्शन प्रदान करता है, जो "तत्काल" से बाहर निकलता है, हालांकि फ़ाइल डिस्क्रिप्टर बंद कर सकता है। यूनिक्स/पॉज़िक्स इस व्यवहार को फ्लैशिंग के बिना सभी एफडी के समापन को अनिवार्य करके बढ़ाता है (और समानार्थी _exit प्रदान करता है)।_+ एक सी ++ प्रोग्राम में व्यवहार कैसे करेगा?

क्या ये फ़ंक्शन static ऑब्जेक्ट्स के लिए विनाशकों को कॉल करेंगे जब C++ प्रोग्राम से कॉल किया जाता है? क्या सी ++ मानक _Exit के बारे में कोई गारंटी देता है?

(this question से प्रेरित होकर, मैं अचानक सोचा ठेठ fork में क्या होता है - exec - C++ में _exit मुहावरा।)

+0

मुझे नहीं लगता कि आपका "कांटा? Exec: _exit" सटीक रूप से कैप्चर करता है कि आमतौर पर इसका उपयोग कैसे किया जाता है। यह और अधिक होगा: "(कांटा == 0)?/* बच्चा */(exec, _exit):/* पैरेंट */(जारी रखें, प्रतीक्षा करें)" – nobar

+1

@ नोबार: मैंने मुहावरे को संक्षिप्त नाम देने की कोशिश की यथासंभव। मुझे डर लगता है कि यह वास्तविक कोड की तरह दिखने से लोगों को टिप्पणी शुरू करने में उत्तेजित करेगा (जैसे "आप त्रुटियों की जांच करना भूल गए हैं")। –

+0

हाँ, मैं उन टिप्पणियों को बना देता। बस मजाक कर रहा है :) वास्तव में, इसके साथ मेरी समस्या यह है कि यह वास्तविक कोड की तरह दिखता है ("?:" ऑपरेटर का उपयोग करके), और चूंकि यह गलत है क्योंकि इससे मुझे कुछ भ्रम पैदा हुआ। – nobar

उत्तर

10

यह बस मानक C++ मौजूद नहीं है, तो वहाँ कोई गारंटी नहीं है।

यह सी ++ 0x में शामिल करने के लिए योजनाबद्ध है। यही कारण है कि निर्दिष्ट करता है (§18.5):

समारोह _Exit (पूर्णांक स्थिति) है इस अंतर्राष्ट्रीय मानक में अतिरिक्त व्यवहार:

- कार्यक्रम स्वचालित, धागे की वस्तुओं के लिए क्रियान्वित विनाशकर्ता के बिना समाप्त हो जाता है , या स्थैतिक भंडारण अवधि और कॉलिंग कॉल किए बिना atexit() (3.6.3) को पारित किया गया।

फॉलोअप:

आईएसओ 12 अगस्त को C++ 0x को मंजूरी दे दी, 2011

+4

लेकिन 'std :: exit()' मौजूद है और यह वैश्विक और स्थैतिक वस्तुओं की सफाई की गारंटी देता है। [3.6.3/1] – wilhelmtell

1

संगामिति और वस्तु विनाश के साथ संबंध में एक दिलचस्प विश्लेषण here नहीं है। जहां तक ​​मुझे पता है, विनाशकों को नहीं बुलाया जाएगा। वर्तमान मानक में इसके बारे में कुछ भी नहीं है।

11

सबसे पहले, कार्यक्रम निकास का कोई भी रूप स्वचालित रूप से ढेर वस्तुओं के लिए विनाशकों को कॉल नहीं करेगा (आईएसओ/आईईसी 14882: 1998 (ई) 12.4.10 में निहित)।

exit() कॉलिंग स्वचालित अवधि वाले ऑब्जेक्ट्स के लिए विनाशकों को कॉल नहीं करेगा, क्योंकि यह उनके संलग्न स्कोप (3.6.1.4) के माध्यम से वापस नहीं आती है। हालांकि, स्थैतिक वस्तुओं के लिए विनाशक को निर्माण के विपरीत क्रम (18.3.8) में बुलाया जाएगा।

कॉलिंग abort() किसी भी प्रकार के ऑब्जेक्ट के लिए किसी भी विनाशक को कॉल नहीं करता है, और न ही यह atexit() पंजीकृत फ़ंक्शन (18.3.3) पर कॉल करता है। मेरे पास सी ++ मानक प्रतिलिपि है जो थोड़ा सा दिनांकित है और _exit या _Exit का उल्लेख नहीं करता है, लेकिन मुझे लगता है कि, यदि मौजूद है, तो उन्हें वही व्यवहार करना चाहिए - यानी, किसी भी विनाशक को फोन नहीं करना चाहिए। विशेष रूप से, सी 99 मानक में, _Exit() स्किप atexit हैंडलर (यह कार्यान्वयन परिभाषित किया गया है कि स्ट्रीम बफर फ़्लश किए गए हैं, खुली धाराएं बंद हैं, या अस्थायी फ़ाइलें हटा दी गई हैं)।

इसके अलावा ध्यान दें कि abort() संकेत SIGABRT (फँसाने द्वारा रद्द किया जा सकता आईएसओ/आईईसी 9899: 1999 (ई) 7.20.4.1.2 - मैं केवल C99 यहाँ है, लेकिन मैं उम्मीद यह संस्करण सी द्वारा संदर्भित में ही होगा ++)। _Exit() नहीं कर सकता।

एक और अधिक व्यावहारिक टिप्पणी पर, abort() और _exit() के सबसे यूनिक्स कार्यान्वयन पर, abort() एक SIGABRT जबकि _exit() बस एक ऑपरेटिंग सिस्टम प्रक्रिया तुरंत समाप्त करने के लिए कॉल कॉल को जन्म देती है। इसका मतलब है कि मुख्य अंतर हैं:

  • आप एक निकास कोड निर्दिष्ट कर सकते हैं _exit()
  • abort() के लिए एक संकेत हैंडलर
  • पर सिस्टम विन्यास, ओएस, और ulimits निर्भर करता है में फंस जा सकता है, abort() में हो सकता है एक कोर डंप या इसी तरह

एक fork()/exec() पैटर्न में, _exit() शायद बेहतर होगा, कोर डंप करने की संभावना से बचने के लिए।

+0

§3.6.1.4 _Exit या "निकास() परिवार" के बारे में कुछ भी नहीं कहता है। यह 'std :: exit 'के बारे में बात करता है। न कुछ ज्यादा, न कुछ कम। –

+0

@ मैथ्यू, क्या हम मानक के समान संशोधन को देख रहे हैं? मैं 1 99 8 के संस्करण को देख रहा हूं, और यह प्रविष्टि "फंक्शन 'शून्य निकास (int) को कॉल करने के साथ शुरू होती है;' '(18.3) में घोषित ..." – bdonlan

+0

मैं n1905 पर देख रहा हूं, जो कि पर आधारित है सी ++ 03। लेकिन "शून्य निकास (int); में घोषित किया गया है" std :: exit' है, इसलिए इसका अर्थ समान लगता है। –

0

मै मैक ओएस पर जीसीसी के साथ एक त्वरित परीक्षण किया और मेरे विनाशकों को बुलाया नहीं गया।

struct A 
{ 
    ~A() 
    { 
     puts("A::~A"); 
    } 
}; 

A globalA; 

int main() 
{ 
    A localA; 
    _exit(0); // or _Exit(0) 
    return 0; 
} 

दूसरी ओर कॉलglobalA के नाशक पर exit(0)

3

तकनीकी रूप से, _Exit सी ++ मानक द्वारा परिभाषित नहीं किया गया है, इसलिए आप इसे 100% पोर्टेबल सी ++ प्रोग्राम से भी कॉल नहीं कर सकते हैं। सी ++ 03 मानक सी 8 9 मानक (उर्फ सी 9 0 या एएनएसआई सी) के संदर्भ में शामिल है, जबकि _Exit केवल नए सी 99 मानक में परिभाषित किया गया है। मुझे यकीन नहीं है कि आने वाले सी ++ 0x मानक में सी का कौन सा संस्करण शामिल है, लेकिन मुझे लगता है कि यह सी 99 पर आधारित है।

_Exit फ़ाइल वर्णनकर्ता बंद करने के लिए गारंटी नहीं है:

किसी भी मामले में, हालांकि, यहां प्रासंगिक भाषा मानकों से प्रासंगिक खंड हैं। C99 §7.20.4.4/2 (जोर मेरा) से:

_Exit समारोह मेजबान पर्यावरण को लौटा दी करने के लिए सामान्य कार्यक्रम समाप्ति होने के लिए और नियंत्रण का कारण बनता है। atexit द्वारा पंजीकृत कोई फ़ंक्शन signal फ़ंक्शन द्वारा पंजीकृत फ़ंक्शन या सिग्नल हैंडलर को फ़ंक्शन नहीं कहा जाता है। होस्ट वातावरण में लौटाई गई स्थिति exit फ़ंक्शन (7.20.4.3) के समान ही निर्धारित की जाती है। चाहे अवांछित buffered डेटा के साथ खुली धाराओं को फ्लश किया गया है, खुली धाराएं बंद हैं, या अस्थायी फ़ाइलें हटा दी गई हैं कार्यान्वयन-परिभाषित है।

याद रखें कि कार्यान्वयन से परिभाषित मतलब यह है कि कार्यान्वयन (जो है, संकलक toolchain और क्रम पर्यावरण) जो कुछ भी यह चाहता है ऐसा करने के लिए चुन सकते हैं, लेकिन यह दस्तावेज़ चाहिए कि क्या यह करता है।

Destructors (12.4) स्थिर भंडारण अवधि (ब्लॉक गुंजाइश पर या नाम स्थान दायरे में घोषित) के initialized वस्तुओं के लिए लौटने की वजह से कहा जाता है:

सी ++ 03 §3.6.3/1 से

मुख्य से और exit (18.3) को कॉल करने के परिणामस्वरूप। इन वस्तुओं को उनके कन्स्ट्रक्टर के पूरा होने या उनके गतिशील प्रारंभिक समापन के विपरीत क्रम में नष्ट कर दिया जाता है।यदि किसी ऑब्जेक्ट को स्थिर रूप से प्रारंभ किया जाता है, तो ऑब्जेक्ट को उसी क्रम में नष्ट कर दिया जाता है जैसे ऑब्जेक्ट गतिशील रूप से प्रारंभ किया गया था। सरणी या वर्ग प्रकार के किसी ऑब्जेक्ट के लिए, उस ऑब्जेक्ट के सभी सबोबजेक्ट्स को किसी भी स्थानीय ऑब्जेक्ट से पहले नष्ट कर दिया जाता है, जिसमें उप-प्रोजेक्ट के निर्माण के दौरान प्रारंभिक स्थिर संग्रहण अवधि नष्ट हो जाती है।

§3.6.3/4:

समारोह

        void abort();

<cstdlib> में घोषित कॉलिंग स्वत: या स्थिर की वस्तुओं के लिए विनाशकर्ता को क्रियान्वित करने के बिना कार्यक्रम समाप्त हो जाता है भंडारण अवधि और कार्यों को कॉल किए बिना atexit() पर भेज दिया गया।

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

+0

थिंको पर मेरा हिस्सा: फाइल डिस्क्रिप्टर सी 99 में मौजूद नहीं है। +1। –

+0

'तकनीकी रूप से, _Exit को C++ मानक द्वारा परिभाषित नहीं किया गया है हां यह है;) –

1

स्थैतिक विनाशकों की कॉलिंग को अयोग्य के संदर्भ में परिभाषित किया गया है। _exit (या _Exit) परिभाषित किया गया है कि अस्थिर हैंडलर चलाने के लिए नहीं। इसलिए स्थिर विनाशकों को किसी भी कार्यान्वयन से नहीं बुलाया जाना चाहिए।

बाहर निकलने पर स्वचालित विनाशकों को भी बुलाया नहीं जाता है()।

तो सी ++ के लिए _Exit अर्थशास्त्र की कोई भी परिभाषा विनाशकों को नहीं चलाएगी।

2

जबकि सी ++ _Exit निर्दिष्ट नहीं करता और C99 यह कार्यान्वयन से परिभाषित है कि क्या यह बफ़र्स flushes छोड़ देता है, POSIX की आवश्यकता है ध्यान दें कि यह है कि यह नहीं फ्लश बफ़र्स (के बाद से इस _exit/_Exit का मुख्य उपयोग, यानी की विफलता से निपटने टूट जाएगा execvefork के बाद)। चूंकि पीओएसईक्स स्वयं को सी ++ मानकों के साथ संरेखित नहीं करता है या किसी भी चीज़ पर उन्हें रोकता है, मुझे लगता है कि यह बहुत ही असंभव है कि सी ++ मानक का भविष्य संस्करण इनमें से किसी भी को बदलने का प्रयास करेगा। यह शायद _Exit निर्दिष्ट नहीं होगा या निर्दिष्ट करेगा कि यह कार्यान्वयन-परिभाषित है।

+0

यह विरोधाभास @ मैट्टू फ्लैंचन का जवाब है कि C++ 0x को' _Exit' के मुद्दे पर C99 से गठबंधन किया गया है, जैसे POSIX ... –

+1

यह नहीं है विरोधाभासी। सी 99 इसे कार्यान्वयन-परिभाषित छोड़ देता है। पीओएसईक्स का पूरा बिंदु सी 99 के शीर्ष पर अतिरिक्त आवश्यकताओं को परिभाषित करना है कि एक सिस्टम को पीओएसईक्स के अनुरूप भी संतुष्ट होना चाहिए। –

2

सी ++ 0x std::quick_exit नामक एक नए फ़ंक्शन को परिभाषित करता है जो किसी भी विनाशक को बुलाए बिना प्रक्रिया को समाप्त करता है। बस चेक किया गया, जी ++ - 4.4.5 पहले ही इसे प्रदान करता है।

0

fork(), exec(), और _exit() सभी POSIX द्वारा परिभाषित कर रहे हैं और वे पूर्व की तारीख कई वर्षों से C99 के _Exit()fork/exec/_exit का उपयोग करने वाले प्रोग्राम C++ का समर्थन करने वाली प्रत्येक प्रणाली के लिए पोर्टेबल नहीं हैं।

_exit() के संबंध में विशेष रूप से, यह एक ऑपरेटिंग सिस्टम कॉल है (POSIX के तहत) फ़ाइलों को बंद कर देगा और प्रक्रिया को सीधे समाप्त कर देगा (लेकिन जरूरी नहीं है)। यह विनाशकों को बुलाए जाने के लिए किसी भी सी ++ तंत्र को बाईपास करेगा।

_Exit() के साथ भी या सी ++ 0x द्वारा प्रदान किया जा रहा है, मुझे संदेह है कि फोर्क के संयोजन के साथ इसका उपयोग करने के लिए बहुत अधिक कारण होगा। यह संभवतः अन्य संदर्भों में "त्वरित-निकास" के लिए व्यापक पोर्टेबिलिटी प्रदान करता है।यदि आप POSIX API का उपयोग कर रहे हैं तो वह कार्यक्षमता पहले से ही _exit() द्वारा कवर की गई है।

प्रोग्राम समाप्ति को C++ 2003 अनुभाग [3.6.3] में संबोधित किया गया है। यह कहता है कि main() रिटर्न और exit() कहलाते समय स्थिर वस्तुओं को पूरी तरह से नष्ट कर दिया जाता है। यह भी कहता है कि abort() कहा जाता है कि ऐसी वस्तुओं को नष्ट नहीं किया जाता है। _exit() को C++ 2003 मानक में संबोधित नहीं किया गया है, लेकिन तथ्य यह है कि यह भाषा-विशिष्ट सफाई को बाईपास करने के लिए है POSIX दस्तावेज़ में वर्णित है। उस प्रभाव को और कहा गया है कि सी ++ मानक में क्या नहीं बताया गया है।

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^