প্রস্থান () এবং গর্ভপাত () ছাড়ার মধ্যে পার্থক্য কী?


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 কারণ, ব্রায়ান আর বন্ডি ভাল ছিল, আপনি গর্ভপাত / প্রস্থান সমস্যা (স্ট্যাক অবজেক্টস ডাকে যা না বলা হয় না) উত্থাপন করেছিলেন এবং একটি RAII- নিবিড় সি ++ প্রক্রিয়াটির বিকল্প প্রস্তাব করেছিলেন।
পেরেেসবাল

আমি ডটরকে ফোন না করেই কোনও প্রোগ্রাম ছাড়ার পথে খুঁজছিলাম এবং আপনার উত্তরটি আমি যা খুঁজছিলাম ঠিক সেটাই! ধন্যবাদ
acemtp

এটি অবশ্যই পুরোপুরি সঠিক, যদি এটি যদি আপনার মজাদার অবজেক্ট ডেস্ট্রাক্টরদের বলা না হয় :-)
ক্রিস হুয়াং-লিভার

আমার জানা মতে, প্রস্থান এবং গর্ভপাতের মধ্যে আরও একটি পার্থক্য হ'ল, যে গর্ভপাতটি (অপারেটিং সিস্টেমের কনফিগারেশনের উপর নির্ভর করে) একটি কোর ডাম্প তৈরি করতে পারে।
ডার্ক হার্মান

33

অ্যাবার্ট একটি 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;
}

মন্তব্যসমূহ:

  • তাহলে পরিত্যাগ uncommented হল: কিছুই ছাপা হয় এবং someobject এর বিনাশকারী নামক করা হবে না।

  • তাহলে পরিত্যাগ উপরে মত মন্তব্য করা হয়: someobject বিনাশকারী বলা হবে আপনি নিম্নলিখিত আউটপুট পাবেন:

প্রস্থান প্রস্থান 2
প্রস্থান ফাংশন 1


এখানে, এটি প্রস্থান ফাংশন 2 ত্যাগ করার ফাংশন 1 বলে। জিসিসি 4, লিনাক্স 2.6।
স্ট্র্যাজার

1
অ্যাকটসিতের জন্য ম্যান পেজ বলে: "ফাংশনগুলি [অ্যাকেক্সিট ব্যবহার করে নিবন্ধিত] বিপরীত ক্রমে ডাকা হয়; কোনও যুক্তি পাস হয় না।"
স্ট্র্যাজার

@ স্ট্রেজারটি ঠিক আছে, অ্যাক্সিট দ্বারা নিবন্ধিত ফাংশনগুলি যখন প্রস্থান হয় বা প্রধান আয় হয় তখন বিপরীত ক্রমে ডাকা হত।
রবার্ট গাম্বল

একটি পরীক্ষা চালানো হয়েছে এবং এটি প্রদর্শিত হয় যে বিশ্বব্যাপী দৃষ্টান্তগুলিতে ধ্বংসকারীদের সমস্ত অ্যাক্সিট কলব্যাকের পরে ডাকা হয়।
স্ট্র্যাজার

লোকদের মনে করিয়ে দেওয়ার জন্য +1 যে ওএস অবশেষে একটি বিসর্জন () কল করার পরেও সমস্ত বরাদ্দের সংস্থানগুলি ফ্রি-আপ করবে।
ফিঙ্গলফিন

10

যখন কোনও প্রোগ্রাম কল exit() কল করে তখন নিম্নলিখিত বিষয়গুলি ঘটে :

  • ফাংশন দ্বারা নিবন্ধিত atexitফাংশনগুলি কার্যকর করা হয়
  • সমস্ত উন্মুক্ত স্ট্রিমগুলি ফ্লাশ এবং বন্ধ করা হয়, এর মাধ্যমে তৈরি করা ফাইলগুলি tmpfileসরানো হবে
  • প্রোগ্রামটি হোস্টের নির্দিষ্ট প্রস্থান কোডের সাথে সমাপ্ত হয়

abort() ফাংশন পাঠায় SIGABRTএটা ধরা না হয় প্রোগ্রাম কোন গ্যারান্টি খোলা স্ট্রিম রাঙা / বন্ধ করা হয় বা মাধ্যমে তৈরি করা অস্থায়ী ফাইল দিয়ে শেষ করা হয়, বর্তমান প্রক্রিয়ায় সংকেত tmpfileসরিয়ে ফেলা হয়, atexitনিবন্ধিত ফাংশন বলা হয় না হয়, এবং একটি অ হোস্টটিতে শূন্য প্রস্থান স্থিতি ফিরে আসে।


হুম। মানটি বলে যে প্রোগ্রামটি কেবলমাত্র সিগন্যাল হ্যান্ডলার "ফিরে না আসে" যদি শেষ হয় না। আপনি সি এর সাথে বেশ ভাল আছেন আপনি কি এমন কোনও দৃশ্যের কল্পনা করতে পারেন যা এটি প্রত্যাবর্তন ছাড়াই স্বাভাবিক কার্যকরকরণ চালিয়ে যাওয়ার অনুমতি দেয়? আমি লংজ্যাম্পের কল্পনা করি তবে সিগন্যাল হ্যান্ডলারে এটি কীভাবে আচরণ করে সে সম্পর্কে আমি নিশ্চিত নই।
জোহানেস স্কাউব -

সাধারণভাবে, সিগন্যাল হ্যান্ডলারের কাছ থেকে লংজ্যাম্প কল করা অপরিজ্ঞাত হয় তবে যখন সিগন্যালটি উত্থাপন / বিসর্জন দিয়ে তৈরি করা হয়েছিল তখন একটি বিশেষ ক্ষেত্রে রয়েছে তাই আমি অনুমান করি যে এটি তাত্ত্বিকভাবে সম্ভব হবে যদিও আমি মনে করি না যে আমি কখনও এটি সম্পন্ন করেছি। এখন আমি এটি চেষ্টা করতে যাচ্ছি;)
রবার্ট গ্যাম্বল

1
এটি কাজ করছে বলে মনে হচ্ছে (300 টি চর সীমাবদ্ধতার কারণে একাধিক পোস্টে বিভক্ত): # অন্তর্ভুক্ত <stdio.h> # অন্তর্ভুক্ত <stdlib.h> # অন্তর্ভুক্ত <সিগন্যাল।> # অন্তর্ভুক্ত <setjmp.h> উদ্বায়ী সিগ_আটমিক_টি ডো_বোর্ট = 1; jmp_buf env; অকার্যকর abort_handler (int i) _ do_abort = 0; লংজ্যাম্প (এনভিভি, 1);}
রবার্ট গ্যাম্বল

int main (শূন্য) {setjmp (env); পুটস ("সেটজেম্পে"); if (do_abort) {সিগন্যাল (SIGABRT, abort_handler); পুটস ("কলিং গর্ভপাত"); পরিত্যাগ (); uts puts ("বাতিল করেনি!"); প্রত্যাবর্তন 0; }
রবার্ট গাম্বল

উবুন্টু 7.04-এ এই মুদ্রণগুলি রয়েছে: সেটজ্যাম্পে কলিং অ্যাওর্টে সেটজ্যাম্পে বাতিল করা হয়নি!
রবার্ট গাম্বল

5

প্রস্থান () ম্যানুয়াল পৃষ্ঠা থেকে:

প্রস্থান () ফাংশনটি স্বাভাবিক প্রক্রিয়াটি সমাপ্ত করে এবং স্থিতির মান & 0377 প্যারেন্টে ফিরে আসে।

গর্ভপাত () ম্যানুয়াল পৃষ্ঠা থেকে:

গর্ভপাত () প্রথমে SIGABRT সিগন্যালটিকে অবরোধ মুক্ত করে এবং তারপরে কলিং প্রক্রিয়াটির জন্য সেই সংকেত উত্থাপন করে। SIGABRT সিগন্যাল ধরা না পড়লে এবং সিগন্যাল হ্যান্ডলারটি ফিরে না আসলে প্রক্রিয়াটির অস্বাভাবিক সমাপ্তির ফলস্বরূপ।


4

abortSIGABRTসংকেত প্রেরণ করে abortকলারে ফিরে আসে না। SIGABRTসিগন্যালের জন্য ডিফল্ট হ্যান্ডলার অ্যাপ্লিকেশনটি বন্ধ করে দেয়। stdioফাইল স্ট্রিমগুলি ফ্লাশ করা হয়, তারপরে বন্ধ করা হয়। সি ++ শ্রেণীর দৃষ্টান্তগুলির জন্য ডেস্ট্রাক্টরগুলি অবশ্য নয় (এটির বিষয়ে নিশ্চিত নন - সম্ভবত ফলাফলগুলি অপরিশোধিত?)।

exitএর নিজস্ব কলব্যাক রয়েছে, সেট করা আছে atexit। যদি কলব্যাকগুলি নির্দিষ্ট করা হয় (বা কেবল একটি), তাদের নিবন্ধের আদেশের বিপরীতে (স্ট্যাকের মতো) বলা হয়, তবে প্রোগ্রামটি প্রস্থান করে। যেমনটি abort, exitকলারে ফিরে আসে না। stdioফাইল স্ট্রিমগুলি ফ্লাশ করা হয়, তারপরে বন্ধ করা হয়। এছাড়াও, সি ++ শ্রেণীর উদাহরণগুলির জন্য ডেস্ট্রাক্টরদের ডাকা হয়।


প্রস্থান করার জন্য অ্যাক্সিটের মাধ্যমে একাধিক কলব্যাক ফাংশন থাকতে পারে, প্রস্থানটি যখন কল করা হয় তখন সমস্ত কলব্যাক ফাংশনগুলি বিপরীত ক্রমে ডাকা হবে যেখানে তারা নিবন্ধিত হয়েছিল।
রবার্ট গাম্বল

@ গ্যাম্বল, অবশ্যই আমি উল্লেখ করেছি যে আমি কয়েক মিনিট আগে @ বন্ডির উত্তরের মন্তব্যে বলেছি। আমি প্রতিফলিত করতে আমার নিজের উত্তর সম্পাদনা করব।
স্ট্রেগার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.