বেশ কয়েকটি উপায় রয়েছে তবে প্রথমে আপনাকে বুঝতে হবে যে কেন অবজেক্ট ক্লিনআপ গুরুত্বপূর্ণ, এবং তাই কারণটি std::exitসি ++ প্রোগ্রামারদের মধ্যে প্রান্তিক করা হয়েছে।
RAII এবং স্ট্যাক আনওয়াইন্ডিং
সি ++ আরএআইআইআই নামে একটি প্রতিমা ব্যবহার করে , যার সহজ ভাষায় অর্থ অবজেক্টগুলি কনস্ট্রাক্টরে আরম্ভ করে এবং ডিস্ট্রাক্টরের ক্লিনআপ করা উচিত। উদাহরণস্বরূপ, std::ofstreamবর্গটি কনস্ট্রাক্টরের সময় ফাইলটি খুলতে পারে, তারপরে ব্যবহারকারী তার উপর আউটপুট ক্রিয়াকলাপ সম্পাদন করে এবং অবশেষে তার জীবনচক্রের শেষে, সাধারণত তার ক্ষেত্র দ্বারা নির্ধারিত হয়, ডেস্ট্রাক্টর বলা হয় যা মূলত ফাইলটি বন্ধ করে এবং ফ্লাশ করে us ডিস্কের মধ্যে কোনও লিখিত সামগ্রী।
আপনি যদি ফাইলটি ফ্লাশ এবং বন্ধ করার জন্য ডেস্ট্রাক্টরের কাছে না যান তবে কী হবে? কে জানে! তবে সম্ভবত এটি ফাইলটি লেখার কথা বলেছিল এমন সমস্ত ডেটা লিখবে না।
উদাহরণস্বরূপ এই কোডটি বিবেচনা করুন
#include <fstream>
#include <exception>
#include <memory>
void inner_mad()
{
throw std::exception();
}
void mad()
{
auto ptr = std::make_unique<int>();
inner_mad();
}
int main()
{
std::ofstream os("file.txt");
os << "Content!!!";
int possibility = /* either 1, 2, 3 or 4 */;
if(possibility == 1)
return 0;
else if(possibility == 2)
throw std::exception();
else if(possibility == 3)
mad();
else if(possibility == 4)
exit(0);
}
প্রতিটি সম্ভাবনার মধ্যে যা ঘটে তা হ'ল:
- সম্ভাব্যতা 1: রিটার্নটি মূলত বর্তমান ফাংশনটির সুযোগ ছেড়ে দেয়, সুতরাং এটি
osতার ডেস্ট্রাক্টরকে কল করার এবং চূড়ান্তভাবে ফাইলটিকে ডিস্কে ফ্লাশ করে ক্লিনআপ করার মাধ্যমে জীবন চক্রের সমাপ্তির বিষয়ে জানে ।
- সম্ভাব্যতা 2: একটি ব্যতিক্রম নিক্ষেপ করাও বর্তমান সুযোগে অবজেক্টগুলির জীবনচক্রের যত্ন নেয়, এইভাবে যথাযথ পরিচ্ছন্নতা করা ...
- সম্ভাব্যতা 3: এখানে স্ট্রাক অযৌক্তিক পদক্ষেপে প্রবেশ করে! যদিও ব্যতিক্রমটি নিক্ষেপ করা হয়েছে
inner_mad, আনভিন্ভার চলে যাবে যদিও স্ট্যাক madএবং mainসঠিক পরিচ্ছন্নতা সম্পাদন করার জন্য, সমস্ত বস্তু যথাযথভাবে ধ্বংস হতে চলেছে, সহ ptrএবং সহ os।
- সম্ভাবনা 4: আচ্ছা, এখানে?
exitএটি একটি সি ফাংশন এবং এটি সচেতন নয় বা সি ++ আইডিয়ামগুলির সাথে সামঞ্জস্যপূর্ণ নয়। এটি খুব একই স্কোপ সহ আপনার জিনিসগুলিতে পরিষ্কার-পরিচ্ছন্নতা সম্পাদন করে নাos । সুতরাং আপনার ফাইলটি সঠিকভাবে বন্ধ হবে না এবং এই কারণে লিখিত সামগ্রীটি কখনও এতে লিখিত হতে পারে না!
- অন্যান্য সম্ভাবনাগুলি: এটি একটি মূল
return 0কার্য সম্পাদন করে এবং সম্ভাব্য 1 এর সমান প্রভাব রাখায়, যথাযথ পরিচ্ছন্নতার দ্বারা এটি কেবল প্রধান সুযোগ ছাড়বে ।
তবে আমি সবেমাত্র আপনাকে যা বলেছিলাম সে সম্পর্কে এতটা নিশ্চিত হন না (মূলত সম্ভাবনাগুলি 2 এবং 3); পড়া চালিয়ে যান এবং আমরা সঠিক ব্যতিক্রম ভিত্তিক ক্লিনআপ কীভাবে সম্পাদন করব তা খুঁজে বের করব।
শেষ হওয়ার সম্ভাব্য উপায়
মূল থেকে ফিরে!
যখনই সম্ভব আপনার এটি করা উচিত; সর্বদা প্রধান থেকে সঠিক প্রস্থান স্থিতি ফিরে আপনার প্রোগ্রাম থেকে ফিরে আসতে পছন্দ করুন।
আপনার প্রোগ্রামের কলার এবং সম্ভবত অপারেটিং সিস্টেমটি আপনার প্রোগ্রামটি যা করার কথা ছিল তা সফলভাবে হয়েছে কিনা তা জানতে চাইতে পারে। এই একই কারণে আপনি হয় শূন্য ফিরে আসতে হবে বা EXIT_SUCCESSপ্রোগ্রামটি সফলভাবে সমাপ্ত হওয়া এবং EXIT_FAILUREসিগন্যাল করার জন্য যে প্রোগ্রামটি সফলভাবে শেষ হয়েছে এবং সিগন্যাল করার জন্য প্রোগ্রামটি অসফলভাবে শেষ হয়েছে, অন্য কোনও ফিরতি মান রূপায়ণ-সংজ্ঞায়িত ( §18.5 / 8 )।
তবে আপনি কল স্ট্যাকের মধ্যে খুব গভীর হতে পারেন এবং এর সমস্তটি ফিরিয়ে দেওয়া বেদনাদায়ক হতে পারে ...
[করবেন না] একটি ব্যতিক্রম নিক্ষেপ
কোনও ব্যতিক্রম ছুঁড়ে দেওয়া পূর্ববর্তী কোনও সুযোগের প্রতিটি বস্তুর ডেস্ট্রাক্টরকে ডেকে স্ট্যাক আনওয়াইন্ডিং ব্যবহার করে সঠিক অবজেক্ট ক্লিনআপ সম্পাদন করবে।
তবে এখানে ধরা ! এটি প্রয়োগ-সংজ্ঞায়িত করা হয় যখন স্ট্রাকযুক্ত ব্যতিক্রম হ্যান্ডেল করা হয় না তখন ক্যাচ (...) ধারা দ্বারা না করা হয় বা noexceptকল স্ট্যাকের মাঝখানে আপনার কোনও ফাংশন থাকে। এটি .515.5.1 এ বলা হয়েছে [ব্যতীত] শেষ করা :
কিছু পরিস্থিতিতে কম সূক্ষ্ম ত্রুটি পরিচালনার কৌশলগুলির জন্য ব্যতিক্রম হ্যান্ডলিং ত্যাগ করা উচিত। [দ্রষ্টব্য: এই পরিস্থিতিগুলি হ'ল:
[...]
- যখন ব্যতিক্রম হ্যান্ডলিং মেকানিজম কোনও ছোঁড়া ব্যতিক্রম (15.3) এর জন্য কোনও হ্যান্ডলারটি খুঁজে না পায় বা যখন কোনও হ্যান্ডলারের সন্ধান (15.3) কোনও noexceptস্পেসিফিকেশন সহ কোনও ফাংশনের বহিরাগত ব্লকের মুখোমুখি হয় যা ব্যতিক্রমটিকে (15.4) অনুমতি দেয় না, বা [...]
[...]
এই জাতীয় ক্ষেত্রে, স্টাড :: টার্মিনেট () বলা হয় (18.8.3)। যে পরিস্থিতিতে কোনও ম্যাচিং হ্যান্ডলার পাওয়া যায় না, স্ট্যান্ড :: টার্মিনেট () বলা হওয়ার আগে স্ট্যাকটি অযাচিত কিনা তা বাস্তবায়ন-সংজ্ঞায়িত হয় [...]
সুতরাং আমাদের এটি ধরতে হবে!
একটি ব্যতিক্রম নিক্ষেপ এবং এটি মূলত ধরা!
যেহেতু অপ্রকাশিত ব্যতিক্রমগুলি স্ট্যাক আনওয়াইন্ডিং সম্পাদন করতে পারে না (এবং ফলস্বরূপ যথাযথ পরিচ্ছন্নতা সম্পাদন করবে না) , তাই আমাদের ব্যতিক্রমটি মূলত ধরা উচিত এবং তারপরে একটি প্রস্থান স্থিতি ( EXIT_SUCCESSবা EXIT_FAILURE) ফিরিয়ে দেওয়া উচিত ।
সুতরাং সম্ভবত একটি ভাল সেটআপ হবে:
int main()
{
/* ... */
try
{
// Insert code that will return by throwing a exception.
}
catch(const std::exception&) // Consider using a custom exception type for intentional
{ // throws. A good idea might be a `return_exception`.
return EXIT_FAILURE;
}
/* ... */
}
[করবেন না] std :: প্রস্থান করুন
এটি কোনও ধরণের স্ট্যাক অযৌক্তিকভাবে সম্পাদন করে না এবং স্ট্যাকের কোনও জীবন্ত অবজেক্ট তার সম্পর্কিত ডেস্ট্রাক্টরকে ক্লিনআপ করার জন্য কল করবে না।
এটি §3.6.1 / 4 [বেসিক.স্টার্ট.ইনাইটে] প্রয়োগ করা হয়েছে :
বর্তমান ব্লকটি ছাড়াই প্রোগ্রামটি সমাপ্তি (উদাহরণস্বরূপ, ফাংশনটি স্ট্যান্ড :: প্রস্থান (ইনট) (18.5) কল করে স্বয়ংক্রিয় স্টোরেজ সময়কাল (12.4) সহ কোনও বস্তু ধ্বংস করে না । স্থিতিশীল বা থ্রেড স্টোরেজ সময়কাল সহ কোনও অবজেক্টের ধ্বংসের সময় যদি কোনও স্ট্যান্ড :: প্রস্থানকে কোনও প্রোগ্রামের সমাপ্তির জন্য বলা হয় তবে প্রোগ্রামটির অপরিবর্তিত আচরণ রয়েছে।
এখনই এটি সম্পর্কে চিন্তা করুন, আপনি কেন এমন কাজ করবেন? আপনি কতগুলি বস্তুর বেদনাদায়ক ক্ষতি করেছেন?
অন্যান্য [খারাপ হিসাবে] বিকল্প
কোনও প্রোগ্রাম বন্ধ করার অন্যান্য উপায় রয়েছে (ক্র্যাশ হওয়া ছাড়াও) তবে তাদের প্রস্তাব দেওয়া হয়নি। কেবল স্পষ্টতার স্বার্থে তারা এখানে উপস্থাপন করতে চলেছে। লক্ষ্য করুন কিভাবে স্বাভাবিক প্রোগ্রাম পরিসমাপ্তি না মানে স্ট্যাকের unwinding কিন্তু একটি ঠিক আছে অপারেটিং সিস্টেমের জন্য রাষ্ট্র।
std::_Exit একটি সাধারণ প্রোগ্রামের সমাপ্তি ঘটায় এবং এটিই।
std::quick_exitএকটি সাধারণ প্রোগ্রামের সমাপ্তি ঘটায় এবং std::at_quick_exitহ্যান্ডলারদের কল করে , অন্য কোনও ক্লিনআপ সম্পন্ন হয় না।
std::exitএকটি সাধারণ প্রোগ্রামের সমাপ্তি ঘটায় এবং তারপরে std::atexitহ্যান্ডলারদের কল করে । অন্যান্য ধরণের ক্লিনআপগুলি স্ট্যাটিক অবজেক্ট ডেস্ট্রাক্টরদের কল করার মতো করা হয়।
std::abortএকটি অস্বাভাবিক প্রোগ্রামের সমাপ্তি ঘটায়, কোনও ক্লিনআপ করা হয় না। প্রোগ্রামটি যদি সত্যিই, সত্যিই অপ্রত্যাশিতভাবে বন্ধ করা হয় তবে এটি বলা উচিত। এটি ওএসকে অস্বাভাবিক সমাপ্তির সংকেত ব্যতীত আর কিছুই করবে না। কিছু সিস্টেম এক্ষেত্রে একটি কোর ডাম্প সম্পাদন করে।
std::terminateকলগুলি std::terminate_handlerযা std::abortডিফল্টরূপে কল করে।
main()ব্যবহার রিটার্ন ফাংশন একটি সঠিক ফেরত মান ব্যবহার করুন অথবা একটি সঠিক ব্যতিক্রম নিক্ষেপ করা। ব্যবহার করবেন নাexit()!