একটি ডেস্ট্রাক্টর বাইরে ব্যতিক্রম নিক্ষেপ


257

বেশিরভাগ লোক বলে যে কখনও ডেস্ট্রাক্টরের বাইরে কোনও ব্যতিক্রম ছুঁড়ে না ফেলে - এর ফলে অনির্ধারিত আচরণের ফলাফল হয়। স্ট্রাস্ট্রপ এই বিষয়টি তুলে ধরেছে যে "ভেক্টর ডেস্ট্রাক্টর স্পষ্টভাবে প্রতিটি উপাদানটির জন্য বিনষ্টকারীকে ডাকে। এটি বোঝাচ্ছে যে কোনও উপাদান ডেস্ট্রাক্টর নিক্ষেপ করলে ভেক্টর ধ্বংস ব্যর্থ হয় ... ডেস্ট্রাক্টর থেকে নিক্ষিপ্ত ব্যতিক্রমগুলি থেকে রক্ষা করার সত্যিই কোনও ভাল উপায় নেই, সুতরাং গ্রন্থাগারটি কোনও উপাদান ধ্বংসকারী "ছুড়লে কোনও গ্যারান্টি দেয় না" (পরিশিষ্ট E3.2 থেকে)

এই নিবন্ধটি অন্যথায় বলে মনে হচ্ছে - ধ্বংসকারীদের ফেলে দেওয়া কম-বেশি ঠিক আছে okay

সুতরাং আমার প্রশ্নটি হ'ল - যদি কোনও ডেস্ট্রাক্টর থেকে ছুঁড়ে ফেলা ফলশ্রুতিহীন আচরণের ফলাফল করে তবে আপনি কীভাবে একজন ডেস্ট্রাক্টরের সময় ঘটে যাওয়া ত্রুটিগুলি পরিচালনা করবেন?

ক্লিনআপ অপারেশনের সময় যদি কোনও ত্রুটি দেখা দেয়, আপনি কি কেবল এটিকে উপেক্ষা করবেন? যদি এটি কোনও ত্রুটি হয় যা সম্ভাব্যভাবে স্ট্যাকটি পরিচালনা করতে পারে তবে ডাস্ট্রেক্টরটিতে সঠিক না হয় তবে এটির জন্য ডেস্ট্রাক্টরের বাইরে কোনও ব্যতিক্রম ছড়িয়ে দেওয়া কি বুদ্ধিমানের কাজ নয়?

স্পষ্টতই এই ধরণের ত্রুটি বিরল, তবে সম্ভব।


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

29
@ স্প্রাফ: আপনি কি জানেন যে আপনি যা বলেছেন তা "আরএআইআইকে দূরে ফেলে" বোঝায়?
কোস

16
@ স্প্রেফ: "বস্তুর সুযোগের বাইরে যাওয়ার আগে একটি পৃথক পদ্ধতি" কল করতে (যেমন আপনি লিখেছেন) আসলে আরআইআইকে দূরে ফেলেছে! এই জাতীয় অবজেক্ট ব্যবহার করে কোডটি নিশ্চিত করতে হবে যে ডেস্ট্রাক্টর ডেকে যাওয়ার আগে এই জাতীয় পদ্ধতিটি কল করা হবে .. অবশেষে, এই ধারণাটি মোটেই সহায়তা করে না।
ফ্রুঙ্কি

8
@ ফ্রনসী নো, কারণ এই সমস্যাটি এই সত্য থেকেই উদ্ভূত যে ধ্বংসকারী কেবলমাত্র সম্পদ প্রকাশের বাইরে কিছু করার চেষ্টা করছেন। এটি "আমি সর্বদা এক্সওয়াইজেড করা শেষ করতে চাই" বলতে লোভনীয় এবং এটি ভেবে যে এটি ডেস্ট্রাক্টরের মধ্যে এই জাতীয় যুক্তি স্থাপনের একটি যুক্তি। না, অলস হবেন না, লিখুন xyz()এবং বিনষ্টকারীকে অ-আরআইআইআই যুক্তি থেকে পরিষ্কার রাখুন।
স্প্রেফ

6
@ ফ্রাঞ্চি উদাহরণস্বরূপ, ফাইলের জন্য কিছু প্রতিশ্রুতিবদ্ধ হওয়া কোনও লেনদেনের প্রতিনিধিত্ব করে এমন কোনও শ্রেণীর ডেস্ট্রাক্টর করার জন্য ঠিকঠাক নয় । যদি প্রতিশ্রুতি ব্যর্থ হয়, যখন লেনদেনের সাথে জড়িত সমস্ত কোড সুযোগের বাইরে চলে যায় তখন এটি পরিচালনা করতে খুব দেরি হয়। কোনও commit()পদ্ধতি না বললে ডেস্ট্রাক্টরের লেনদেনটি বাতিল করা উচিত ।
নিকোলাস উইলসন

উত্তর:


197

একজন ডেস্ট্রাক্টরের বাইরে একটি ব্যতিক্রম ছুঁড়ে ফেলা বিপজ্জনক।
যদি আর একটি ব্যতিক্রম ইতিমধ্যে প্রচার করে তবে অ্যাপ্লিকেশনটি শেষ হবে।

#include <iostream>

class Bad
{
    public:
        // Added the noexcept(false) so the code keeps its original meaning.
        // Post C++11 destructors are by default `noexcept(true)` and
        // this will (by default) call terminate if an exception is
        // escapes the destructor.
        //
        // But this example is designed to show that terminate is called
        // if two exceptions are propagating at the same time.
        ~Bad() noexcept(false)
        {
            throw 1;
        }
};
class Bad2
{
    public:
        ~Bad2()
        {
            throw 1;
        }
};


int main(int argc, char* argv[])
{
    try
    {
        Bad   bad;
    }
    catch(...)
    {
        std::cout << "Print This\n";
    }

    try
    {
        if (argc > 3)
        {
            Bad   bad; // This destructor will throw an exception that escapes (see above)
            throw 2;   // But having two exceptions propagating at the
                       // same time causes terminate to be called.
        }
        else
        {
            Bad2  bad; // The exception in this destructor will
                       // cause terminate to be called.
        }
    }
    catch(...)
    {
        std::cout << "Never print this\n";
    }

}

এটি মূলত:

বিপজ্জনক যে কোনও কিছু (যেমন এটি একটি ব্যতিক্রম ছুঁড়ে দিতে পারে) সর্বসাধারণের পদ্ধতিগুলির মাধ্যমে করা উচিত (অগত্যা সরাসরি নয়)। আপনার শ্রেণীর ব্যবহারকারী তারপরে পাবলিক পদ্ধতি ব্যবহার করে এবং কোনও সম্ভাব্য ব্যতিক্রম ধরা পরে সম্ভাব্য এই পরিস্থিতিগুলি পরিচালনা করতে পারে।

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

সুতরাং কার্যকরভাবে আপনি ব্যবহারকারীর উপর এই দায়িত্বটি পাস করেন। যদি ব্যবহারকারী ব্যতিক্রমগুলি সংশোধন করার মতো অবস্থানে থাকে তবে তারা ম্যানুয়ালি উপযুক্ত ফাংশনগুলি কল করবে এবং কোনও ত্রুটি প্রসেস করবে। যদি বস্তুর ব্যবহারকারীর উদ্বেগ না থাকে (কারণ বস্তুটি ধ্বংস হয়ে যাবে) তবে বিনষ্টকারী ব্যবসায়ের যত্ন নেবেন।

একটি উদাহরণ:

এসটিডি :: fstream

কাছাকাছি () পদ্ধতিটি সম্ভবত একটি ব্যতিক্রম ছুঁড়ে ফেলতে পারে। ফাইলটি খোলা থাকলে ডেস্ট্রাক্টর কল () কল করে তবে নিশ্চিত হন যে কোনও ব্যতিক্রম ডেস্ট্রাক্টরের বাইরে প্রচার না করে।

সুতরাং কোনও ফাইল অবজেক্টের ব্যবহারকারী যদি ফাইলটি বন্ধ করার সাথে সম্পর্কিত সমস্যাগুলির জন্য বিশেষ পরিচালনা করতে চায় তবে তারা ম্যানুয়ালি কল () কল করবে এবং কোনও ব্যতিক্রম হ্যান্ডেল করবে। অন্যদিকে তারা যদি যত্ন না করে তবে ধ্বংসকারীকে পরিস্থিতি সামাল দেওয়ার জন্য রেখে দেওয়া হবে।

স্কট মায়ার্স তাঁর "কার্যকর সি ++" বইয়ে বিষয়টি সম্পর্কে একটি চমৎকার নিবন্ধ রয়েছে

সম্পাদনা:

স্পষ্টতই "আরও কার্যকর সি ++"
আইটেম 11 এ: ডেস্ট্রাক্টরগুলি ছেড়ে যাওয়া থেকে ব্যতিক্রমগুলি রোধ করুন


5
"আপনি যদি সম্ভাব্যভাবে অ্যাপ্লিকেশনটি বন্ধ করতে আপত্তি না করেন তবে আপনার সম্ভবত ত্রুটিটি গ্রাস করা উচিত" " - এটি সম্ভবত নিয়মের চেয়ে ব্যতিক্রম (ক্ষমাের ক্ষমা) হওয়া উচিত - যা দ্রুত ব্যর্থ হওয়া।
এরিক ফোর্বস

15
আমি একমত নই প্রোগ্রামটি সমাপ্তি স্ট্যাকটি আনওয়াইন্ড বন্ধ করে দেয়। আর কোনও ডেস্ট্রাক্টর ডাকা হবে না। যে কোনও সংস্থান খোলা থাকবে তা খোলা রেখে দেওয়া হবে। আমি মনে করি ব্যতিক্রমটিকে গ্রাস করা পছন্দনীয় বিকল্প হবে।
মার্টিন ইয়র্ক

20
ওএস অ্যাকানগুলি সম্পদ পরিষ্কার করে এটি মালিক বন্ধ the মেমোরি, ফাইলহ্যান্ডলস ইত্যাদি জটিল সংস্থান সম্পর্কে কী: ডিবি সংযোগ। আপনি যে আইএসএস খোলেন তাতে আপলিংক (এটি কি স্বয়ংক্রিয়ভাবে নিকটবর্তী সংযোগগুলি প্রেরণ করবে)? আমি নিশ্চিত নাসা চাইবে আপনি সংযোগটি পরিষ্কারভাবে বন্ধ করে দিন!
মার্টিন ইয়র্ক

7
যদি কোনও অ্যাপ্লিকেশনটি বাতিল করে "দ্রুত ব্যর্থ" হতে চলেছে, তবে এটি প্রথমে ব্যতিক্রম ছোঁড়া উচিত নয়। যদি এটি স্ট্যাক ব্যাক আপ ব্যাক আপ করে ব্যর্থ হতে চলেছে, তবে এটি এমনভাবে করা উচিত নয় যা প্রোগ্রামটি বাতিল হয়ে যেতে পারে। একটি বা অন্য, উভয় বাছাই করবেন না।
টম

2
@ লোকিআস্টারি আপনি কোনও মহাকাশযানের সাথে যোগাযোগের জন্য যে পরিবহন প্রোটোকলটি ব্যবহার করছেন তা কি কোনও বাদ পড়া সংযোগটি পরিচালনা করতে পারে না? ঠিক আছে ...
ডগ 656536

54

কোনও ডেস্ট্রাক্টরের বাইরে ফেলে দেওয়ার ফলে ক্র্যাশ হতে পারে, কারণ এই ডেস্ট্রাক্টরকে "স্ট্যাক আনওয়াইন্ডিং" এর অংশ হিসাবে ডাকা যেতে পারে। স্ট্যাক আনওয়াইন্ডিং এমন একটি প্রক্রিয়া যা কোনও ব্যতিক্রম ছুঁড়ে ফেলা হলে ঘটে। এই পদ্ধতিতে, "চেষ্টা" করার পরে এবং ব্যতিক্রম ছোঁড়ার আগ পর্যন্ত সমস্ত বস্তু স্ট্যাকের মধ্যে ঠেলে দেওয়া হবে - তাদের ধ্বংসকারীদের ডাকা হবে। এবং এই প্রক্রিয়া চলাকালীন, অন্য একটি ব্যতিক্রম নিক্ষেপ অনুমোদিত নয়, কারণ এটি একবারে দুটি ব্যতিক্রম পরিচালনা করা সম্ভব নয়, এইভাবে, এটি কলটি বাতিল করতে প্ররোচিত করবে (), প্রোগ্রামটি ক্রাশ হয়ে যাবে এবং নিয়ন্ত্রণটি OS এ ফিরে আসবে।


1
আপনি কি দয়া করে উপরের পরিস্থিতিতে কীভাবে অ্যাবੋਰਟ () ডেকে পাঠালেন তা বিস্তারিতভাবে বর্ণনা করতে পারেন। মানে ফাঁসির নিয়ন্ত্রণটি এখনও সি ++ সংকলকের সাথে ছিল
কৃষ্ণ ওজা

1
@ কৃষ্ণ_উজা: বেশ সহজ: যখনই কোনও ত্রুটি নিক্ষেপ করা হয়, ত্রুটি উত্থাপনকারী কোডটি কিছুটা পরীক্ষা করে যা ইঙ্গিত করে যে রানটাইম সিস্টেমটি আনওয়াইন্ডিং স্ট্যাকের প্রক্রিয়াধীন রয়েছে (অর্থাত্, অন্য কিছুকে পরিচালনা করছে তবে এখনও এটির জন্য throwকোনও catchব্লক খুঁজে পাওয়া যায়নি )) যে ক্ষেত্রে std::terminate(না abort) এর পরিবর্তে একটি (নতুন) ব্যতিক্রম উত্থাপন (অথবা স্ট্যাকের unwinding অব্যাহত) এর বলা হয়।
মার্ক ভ্যান লিউউয়েন

53

আমরা আছে পার্থক্য এখানে পরিবর্তে অন্ধ নিম্নলিখিত সাধারণ জন্য উপদেশ নির্দিষ্ট ক্ষেত্রে।

নোট করুন যে নীচের বিষয়বস্তুগুলির ধারকগুলির বিষয়টি এবং কন্টেইনারের অভ্যন্তরে একাধিক ডিটেক্টরের সামগ্রীতে কী করা উচিত তা উপেক্ষা করে। (এবং এটি আংশিকভাবে উপেক্ষা করা যেতে পারে, কারণ কিছু বস্তু কেবল পাত্রে রাখার পক্ষে উপযুক্ত নয়))

আমরা যখন দুই ধরণের ক্লাস বিভক্ত করি তখন পুরো সমস্যাটি ভাবতে সহজ হয়। একজন শ্রেণির শিক্ষকের দুটি পৃথক দায়িত্ব থাকতে পারে:

  • (আর) রিলিজ শব্দার্থবিজ্ঞান (ওরফে মুক্ত সেই স্মৃতি)
  • (গ) কমিট শব্দার্থবিদ্যা (ওরফে ফ্লাশ ডিস্কে ফাইল)

যদি আমরা প্রশ্নটি এইভাবে দেখি, তবে আমি মনে করি যে এটি যুক্তিযুক্ত হতে পারে যে (আর) শব্দার্থবিজ্ঞানগুলি কখনই কোনও ড্টারের কাছ থেকে ব্যতিক্রম ঘটায় না কারণ ক) এটি সম্পর্কে আমরা কিছুই করতে পারি না এবং খ) অনেকগুলি মুক্ত-সংস্থান ক্রিয়াকলাপগুলি করে না এমনকি ত্রুটি যাচাইয়ের জন্য সরবরাহ করুন, যেমন ।void free(void* p);

(সি) শব্দার্থবিজ্ঞানের সাথে অবজেক্টস যেমন কোনও ফাইল অবজেক্টের জন্য যা সফলভাবে এটির ডেটা বা ফ্ল্যাশ করা প্রয়োজন ("স্কোপ রক্ষিত") ডাটাবেস সংযোগ যা ড্টরে কমিট করে তা আলাদা ধরণের: আমরা ত্রুটি সম্পর্কে কিছু করতে পারি (চালু) অ্যাপ্লিকেশন স্তর) এবং আমাদের সত্যিই এমনভাবে চলতে হবে না যেন কিছুই ঘটেছিল।

আমরা যদি RAII রুটটি অনুসরণ করি এবং তাদের ডিটারগুলিতে (সি) শব্দার্থবিজ্ঞানযুক্ত অবজেক্টগুলিকে অনুমতি দিই তবে আমি মনে করি আমাদের তখন সেইরকম বিজোড় ক্ষেত্রেও অনুমতি দিতে হবে যেখানে এই ধরনের ডিটাররা নিক্ষেপ করতে পারে। এটি অনুসরণ করে যে আপনার পাত্রে এই ধরণের জিনিসগুলি রাখা উচিত নয় এবং এটিও অনুসরণ করে যে প্রোগ্রামটি যদি এখনও terminate()কোনও ব্যতিক্রম সক্রিয় থাকাকালীন কোনও কমিট-ডটর নিক্ষেপ করতে পারে তবে।


ত্রুটি পরিচালনার বিষয়ে (কমিট / রোলব্যাক শব্দার্থবিজ্ঞান) এবং ব্যতিক্রমগুলি সম্পর্কে, একজন আন্দ্রেই আলেকজান্দ্রেস্কু দ্বারা একটি ভাল আলোচনা হয়েছে : সি ++ / ডিক্লারেটিভ কন্ট্রোল ফ্লোতে ত্রুটি হ্যান্ডলিং ( এনডিসি 2014 এ অনুষ্ঠিত )

বিশদগুলিতে তিনি ব্যাখ্যা করেছেন যে কীভাবে ফলি লাইব্রেরি UncaughtExceptionCounterতাদের ScopeGuardসরঞ্জামকরণের জন্য একটি প্রয়োগ করে ।

(আমার মনে রাখা উচিত অন্যদেরও একই ধারণা ছিল))

যদিও আলাপটি ডিটটার থেকে নিক্ষেপ করার দিকে মনোনিবেশ করে না, এটি এমন একটি সরঞ্জাম দেখায় যা আজকে কোনও ডিটার থেকে ফেলে দেওয়ার সময় সমস্যাগুলি থেকে মুক্তি পেতে ব্যবহার করা যেতে পারে used

ইন ভবিষ্যতে সেখানে পারে একটি এসটিডি বৈশিষ্ট্যটি এই জন্য, হতে দেখতে N3614 , এবং এটি সম্পর্কে আলোচনা

আপডেট '17: এর জন্য সি ++ 17 std::uncaught_exceptionsস্ট্যান্ড বৈশিষ্ট্যটি আফিকেট। আমি দ্রুত সিপিপিআরএফ নিবন্ধটি উদ্ধৃত করব:

মন্তব্য

উদাহরণস্বরূপ যেখানে intপুনর্বারিতকরণ uncaught_exceptionsব্যবহৃত হয় তা হল ... ... প্রথমে একটি গার্ড অবজেক্ট তৈরি করে এবং তার নির্মাত্রে অপ্রকাশিত ব্যতিক্রমগুলির সংখ্যা রেকর্ড করে। আউটপুটটি গার্ড অবজেক্টের ডেস্ট্রাক্টর দ্বারা সম্পাদিত হয় যতক্ষণ না foo () নিক্ষেপ না করে ( ক্ষেত্রে ক্ষেত্রে কনস্ট্রাক্টর অবলম্বনের চেয়ে নির্ধারিত ব্যতিক্রম সংখ্যা বেশি )


6
অত্যন্ত সম্মত। এবং আরও একটি শব্দার্থক (Ro) রোলব্যাক শব্দার্থ যুক্ত। স্কোপ গার্ডে সাধারণত ব্যবহৃত হয়। আমার প্রকল্পের ক্ষেত্রে যেমন আমি একটি ওএনএসসিওপি.এইএসআইটি ম্যাক্রো সংজ্ঞায়িত করেছি। রোলব্যাক শব্দার্থ সম্পর্কে ঘটনাটি এখানে অর্থবহ কিছু ঘটতে পারে। সুতরাং আমাদের সত্যই ব্যর্থতা উপেক্ষা করা উচিত নয়।
ওয়েপিং এল

আমি মনে করি যে ধ্বংসকারীদের কাছে আমরা শব্দার্থকতা করার একমাত্র কারণ হ'ল সি ++ সমর্থন করে না finally
ব্যবহারকারী541686

@Mehrdad: finally হয় একটি dtor। এটি সবসময় বলা হয়, যাই হোক না কেন। অবশেষে সিনট্যাক্টিক আনুমানিক জন্য, বিভিন্ন স্কোপ_গার্ড বাস্তবায়ন দেখুন। আজকাল, জায়গায় জায়গায় যন্ত্রপাতি সহ (এমনকি স্ট্যান্ডার্ডেও কি এটি সি ++ ১৪?) সনাক্ত করার জন্য যে ডর্টরটি নিক্ষেপ করার অনুমতি রয়েছে কিনা, এমনকি এটি সম্পূর্ণ নিরাপদও করা যেতে পারে।
মার্টিন বা 11

1
@ মার্টিনবা: আমি মনে করি আপনি আমার মন্তব্যের মূল বক্তব্য মিস করেছেন, যা অবাক করার মতো যেহেতু আমি (আর) এবং (সি) আলাদা বলে আপনার ধারণার সাথে একমত হয়েছি। আমি বলার চেষ্টা করছিলাম যে একটি ডর্টর সহজাতভাবে (আর) এর finallyএকটি সরঞ্জাম এবং সহজাতভাবে (সি) এর একটি সরঞ্জাম। যদি আপনি না দেখেন তবে: কেন একে অপরের উপরে finallyব্লকগুলিতে ব্যতিক্রম ছড়িয়ে দেওয়া বৈধ , এবং কেন ধ্বংসকারীদের ক্ষেত্রে এটি একই নয় তা বিবেচনা করুন । (কিছু অর্থে, এটা একটি ব্যাপার তথ্য বনাম নিয়ন্ত্রণ । জিনিস Destructors তথ্য মুক্তি জন্য, finallyনিয়ন্ত্রণ মুক্তি জন্য তারা বিভিন্ন; এটি দুর্ভাগ্য যে সি ++ তাদের একসঙ্গে বন্ধন যুক্ত করে।।)
user541686

1
@ মেহরদাদ: এখানে অনেক বেশি সময় কাটাচ্ছেন। আপনি যদি চান তবে আপনি নিজের যুক্তিগুলি এখানে তৈরি করতে পারেন: প্রোগ্রামার.সটাকেক্সচেঞ্জ / প্রশ্ন / 304067/… । ধন্যবাদ।
মার্টিন বা

21

একজন ডেস্ট্রাক্টর থেকে নিক্ষেপ সম্পর্কে নিজেকে জিজ্ঞাসা করার আসল প্রশ্নটি "কলার এটি দিয়ে কী করতে পারে?" ব্যতিক্রমের সাথে আপনি কী করতে পারেন এমন আসলেই কি কার্যকর কিছু রয়েছে যা কোনও ডেস্ট্রাক্টর থেকে নিক্ষেপ করে তৈরি হওয়া বিপদগুলিকে পূরণ করে?

আমি যদি কোনও Fooবস্তু ধ্বংস করি এবং Fooধ্বংসকারী কোনও ব্যতিক্রম টস করে, আমি যুক্তিযুক্তভাবে এটি কী করতে পারি? আমি এটি লগ করতে পারি, বা আমি এটিকে উপেক্ষা করতে পারি। এখানেই শেষ. আমি এটি "ঠিক" করতে পারছি না, কারণ Fooবস্তুটি ইতিমধ্যে চলে গেছে। সর্বোত্তম ক্ষেত্রে, আমি ব্যতিক্রমটি লগইন করি এবং এমনভাবে চালিয়ে যাচ্ছি যেন কিছুই ঘটে না (বা প্রোগ্রামটি সমাপ্ত করে)। কোনও ডেস্ট্রাক্টর থেকে নিক্ষেপ করে এমন কি অসম্ভব সংশোধিত আচরণের কারণ হতে পারে?


11
সবেমাত্র লক্ষ্য করা গেছে ... ডাক্তার থেকে নিক্ষেপ করা কখনই অপরিজ্ঞাত আচরণ নয়। অবশ্যই, এটি কলটিমেট () বলতে পারে, তবে এটি অত্যন্ত সুনির্দিষ্ট আচরণ behavior
মার্টিন বা

4
std::ofstreamএর ডেস্ট্রাক্টর ফ্লাশ করে ফাইলটি বন্ধ করে দেয়। ফ্লাশ করার সময় একটি ডিস্ক পূর্ণ ত্রুটি ঘটতে পারে, যার সাহায্যে আপনি একেবারে দরকারী কিছু করতে পারেন: ব্যবহারকারীকে ডিস্কের ডায়ালগটি ফাঁকা না করে বলে একটি ত্রুটি ডায়ালগ দেখান।
অ্যান্ডি

13

এটি বিপজ্জনক, তবে এটি একটি পঠনযোগ্যতা / কোড বোধগম্যতার দিক থেকেও বোঝায় না।

আপনার যা জিজ্ঞাসা করতে হবে তা এই পরিস্থিতিতে

int foo()
{
   Object o;
   // As foo exits, o's destructor is called
}

কি ব্যতিক্রম ধরা উচিত? ফোন করা উচিত? নাকি এফও হ্যান্ডেল করা উচিত? অভ্যর্থনা সম্পর্কিত অভ্যন্তরীণ কিছু সম্পর্কে foo এর কলার কেন যত্ন নেওয়া উচিত? ভাষা বোঝার জন্য এটি একটি উপায় সংজ্ঞায়িত করতে পারে তবে এটি অপঠনযোগ্য এবং বুঝতে অসুবিধা হতে চলেছে।

আরও গুরুত্বপূর্ণ বিষয়, অবজেক্টের জন্য স্মৃতি কোথায় যায়? বস্তুর মালিকানাধীন স্মৃতিটি কোথায় যায়? এটি এখনও বরাদ্দ করা হয়েছে (সম্ভবত এটি ধ্বংসকারী ব্যর্থ হয়েছে বলে)? বিষয়টি বিবেচনা করুন যে বস্তুটি স্ট্যাক স্পেসে ছিল তাই এটি অবশ্যই নির্বিশেষে চলে গেল।

তারপরে এই মামলাটি বিবেচনা করুন

class Object
{ 
   Object2 obj2;
   Object3* obj3;
   virtual ~Object()
   {
       // What should happen when this fails? How would I actually destroy this?
       delete obj3;

       // obj 2 fails to destruct when it goes out of scope, now what!?!?
       // should the exception propogate? 
   } 
};

অবজেক্ট 3-এর মোছাটি ব্যর্থ হয়ে গেলে, আমি কীভাবে এমনভাবে মুছে ফেলব যা গ্যারান্টিযুক্ত ব্যর্থ না হয়? এটা আমার স্মৃতি বাঁধা!

এখন প্রথম কোড স্নিপেটে বিবেচনা করুন অবজেক্টটি স্বয়ংক্রিয়ভাবে চলে যায় কারণ এটি স্ট্যাকের মধ্যে যখন অবজেক্ট 3 হিপ রয়েছে। যেহেতু অবজেক্ট 3-এর পয়েন্টারটি চলে গেছে, আপনি ধরণের এসএল। আপনার একটি স্মৃতি ফুটো আছে।

জিনিসগুলি করার এখন একটি নিরাপদ উপায় নিম্নলিখিতটি

class Socket
{
    virtual ~Socket()
    {
      try 
      {
           Close();
      }
      catch (...) 
      {
          // Why did close fail? make sure it *really* does close here
      }
    } 

};

এই FAQ দেখুন


এই উত্তরটি পুনরুত্থিত করা, পুনরায়: প্রথম উদাহরণ হিসাবে, int foo()আপনি যদি এটি করা যত্নবান হন তবে ডিস্ট্রিক্টরদের ধরার পাশাপাশি, একটি চেষ্টা-ব্লকে পুরো ফাংশন ফুটিকে মোড়ানোর জন্য একটি ফাংশন-ট্রাই-ব্লক ব্যবহার করতে পারেন। এখনও পছন্দসই পদ্ধতির নয়, তবে এটি একটি জিনিস।
tyree731

13

সি ++ (আইএসও / আইইসি জেটিসি 1 / এসসি 22 এন 4411) এর আইএসও খসড়া থেকে

সুতরাং ডেস্ট্রাক্টরদের সাধারণত ব্যতিক্রমগুলি ধরা উচিত এবং তাদেরকে ডেস্ট্রাক্টরের বাইরে প্রচার করতে দেওয়া উচিত নয়।

3 চেষ্টা ব্লক থেকে একটি নিক্ষেপ-অভিব্যক্তি পর্যন্ত পথে নির্মিত স্বয়ংক্রিয় বস্তুর জন্য ডেস্ট্রাক্টরদের কল করার প্রক্রিয়াটিকে "স্ট্যাক আনওয়াইন্ডিং" বলা হয়। [দ্রষ্টব্য: স্ট্যাক আনওয়াইন্ডিং চলাকালীন কোনও ডাস্ট্রাস্টার যদি ব্যতিক্রম বাদ দেয় তবে স্ট্যান্ড :: টার্মিনেট বলা হয় (15.5.1)। সুতরাং ডেস্ট্রাক্টরদের সাধারণত ব্যতিক্রমগুলি ধরা উচিত এবং তাদেরকে ডেস্ট্রাক্টরের বাইরে প্রচার করতে দেওয়া উচিত নয়। - শেষ নোট]


1
প্রশ্নের উত্তর দেয়নি - ওপি ইতিমধ্যে এটি সম্পর্কে অবগত।
আরাফাঙ্গিয়ন

2
@ আরাফানজিওন আমার সন্দেহ হয় যে তিনি গ্রহণযোগ্য উত্তরটি ঠিক একই পয়েন্ট হিসাবে তৈরি করেছেন বলে তিনি (স্ট্যান্ডার্ড :: ডাকা হবে বলা হচ্ছে) অবগত ছিলেন।
লোথার

@ আরাফ্যাঙ্গিয়ান যেমন এখানে কিছু উত্তরে কিছু লোক উল্লেখ করেছেন যে গর্ভপাত () বলা হচ্ছে; অথবা এটি যে std :: টার্নেট ইন টার্নসকে abort () ফাংশন বলে।
কৃষ্ণা ওজা

7

আপনার ডেস্ট্রাক্টর অন্যান্য ডেস্ট্রাক্টরগুলির একটি শৃঙ্খলের অভ্যন্তরে চালিত হতে পারে। আপনার তাত্ক্ষণিক কলার দ্বারা ধরা পড়ে না এমন একটি ব্যতিক্রম ছুঁড়ে ফেলা একাধিক বস্তুটিকে একটি বেমানান অবস্থায় ফেলে দিতে পারে, ফলে আরও বেশি সমস্যা দেখা দেয় তারপর ক্লিনআপ অপারেশনে ত্রুটি উপেক্ষা করে।


7

আমি সেই গোষ্ঠীতে রয়েছি যা বিবেচনা করে যে "স্কোপড গার্ড" প্যাটার্নটি নষ্টকারীতে নিক্ষেপ করা হয়েছে তা অনেক পরিস্থিতিতে কার্যকর - বিশেষত ইউনিট পরীক্ষার জন্য। তবে, সচেতন থাকুন যে সি ++ 11 এ, ডেস্ট্রাক্টরকে ছুঁড়ে ফেলা ফলস্বরূপ কল করার জন্য ডেকে std::terminateআনা হয় যেহেতু ডেস্ট্রাক্টরগুলি স্পষ্টভাবে মন্তব্য করা হয় noexcept

আন্দ্রেজে ক্রজেমিয়েস্কির ধ্বংসকারীদের বিষয়ে একটি দুর্দান্ত পোস্ট রয়েছে যা নিক্ষেপ করে:

তিনি উল্লেখ করেছেন যে সি ++ 11 এ noexceptধ্বংসকারীদের জন্য ডিফল্টকে ওভাররাইড করার একটি ব্যবস্থা আছে :

সি ++ ১১-এ, একজন ডেস্ট্রাস্টারকে স্পষ্টভাবে নির্দিষ্ট করা হয়েছে noexcept। এমনকি যদি আপনি কোনও স্পেসিফিকেশন যোগ না করেন এবং আপনার ডেস্ট্রাক্টরকে এভাবে নির্ধারণ করেন:

  class MyType {
        public: ~MyType() { throw Exception(); }            // ...
  };

সংকলকটি এখনও অদৃশ্যভাবে noexceptআপনার ধ্বংসকারীকে স্পেসিফিকেশন যুক্ত করবে will এবং এর অর্থ হ'ল যে কোনও মুহুর্তে আপনার ধ্বংসকারী একটি ব্যতিক্রম ছুঁড়ে std::terminateমারবে, তাকে ডাকা হবে, এমনকি যদি কোনও দ্বৈত-ব্যতিক্রম পরিস্থিতি না ঘটে। আপনি যদি সত্যই আপনার ধ্বংসকারীদের নিক্ষেপ করার অনুমতি দেওয়ার জন্য দৃ determined় প্রতিজ্ঞ হন তবে আপনাকে এটি স্পষ্টভাবে নির্দিষ্ট করতে হবে; আপনার কাছে তিনটি বিকল্প রয়েছে:

  • আপনার ধ্বংসকারীকে স্পষ্টভাবে উল্লেখ করুন noexcept(false),
  • আপনার ক্লাসটিকে অন্য একটি থেকে উত্তরাধিকারী করুন যা এর ডিস্ট্রাক্টর হিসাবে ইতিমধ্যে নির্দিষ্ট করে noexcept(false)
  • আপনার ক্লাসে একটি অ স্থিতিশীল ডেটা সদস্য রাখুন যা ইতিমধ্যে এর ডেস্ট্রাক্টর হিসাবে নির্দিষ্ট করে noexcept(false)

অবশেষে, আপনি যদি ডেস্ট্রাক্টর নিক্ষেপ করার সিদ্ধান্ত নেন, আপনার সর্বদা দ্বিগুণ ব্যতিক্রম হওয়ার ঝুঁকি সম্পর্কে সচেতন হওয়া উচিত (একটি ব্যতিক্রমের কারণে স্ট্যাকটি উন্মুক্ত হওয়ার সময় নিক্ষেপ করা)। এটির জন্য কল আসবে std::terminateএবং এটি আপনি যা চান তা খুব কমই হয়। এই আচরণটি এড়ানোর জন্য, আপনি নতুন করে ব্যবহার করার আগে ইতিমধ্যে কোনও ব্যতিক্রম আছে কিনা তা পরীক্ষা করে দেখতে পারেন std::uncaught_exception()


6

অন্য প্রত্যেকে ব্যাখ্যা করেছেন যে ধ্বংসকারীদের ফেলে দেওয়া কেন ভয়ঙ্কর ... আপনি এটি সম্পর্কে কী করতে পারেন? যদি আপনি কোনও অপারেশন করছেন যা ব্যর্থ হতে পারে তবে একটি পৃথক পাবলিক পদ্ধতি তৈরি করুন যা পরিষ্কার-পরিচ্ছন্নতা সম্পাদন করে এবং যথেচ্ছ ব্যতিক্রম ছুঁড়ে ফেলতে পারে। বেশিরভাগ ক্ষেত্রে, ব্যবহারকারীরা এটিকে উপেক্ষা করবেন। ব্যবহারকারীরা যদি ক্লিনআপের সাফল্য / ব্যর্থতা পর্যবেক্ষণ করতে চান তবে তারা কেবল পরিষ্কার ক্লিনআপ রুটিন কল করতে পারেন।

উদাহরণ স্বরূপ:

class TempFile {
public:
    TempFile(); // throws if the file couldn't be created
    ~TempFile() throw(); // does nothing if close() was already called; never throws
    void close(); // throws if the file couldn't be deleted (e.g. file is open by another process)
    // the rest of the class omitted...
};

আমি একটি সমাধান খুঁজছি কিন্তু তারা কী হয়েছে এবং কেন তা ব্যাখ্যা করার চেষ্টা করছে। কেবল এটি পরিষ্কার করে দিতে চান ঘনিষ্ঠ ফাংশনটি ডেস্ট্রাক্টরের ভিতরে ডাকা হয়?
জেসন লিউ

5

মূল উত্তরগুলির সংযোজন হিসাবে, যা ভাল, ব্যাপক এবং নির্ভুল, আমি আপনার উল্লেখ করা নিবন্ধটি সম্পর্কে মন্তব্য করতে চাই - যেটি বলে যে "ধ্বংসকারীদের মধ্যে ব্যতিক্রম নিক্ষেপ করা এত খারাপ নয়"।

নিবন্ধটি "ব্যতিক্রম নিক্ষেপের বিকল্পগুলি কী" এই লাইনটি নিয়েছে এবং প্রতিটি বিকল্পের সাথে কিছু সমস্যা তালিকাভুক্ত করেছে। এটি করার পরে সিদ্ধান্তে আসে যে আমরা সমস্যা-মুক্ত বিকল্প খুঁজে না পাওয়ায় আমাদের ব্যতিক্রম ছুঁড়ে ফেলা উচিত।

সমস্যাটি হ'ল বিকল্পগুলির সাথে তালিকাভুক্ত সমস্যাগুলির মধ্যে যে কোনও একটিই ব্যতিক্রম আচরণের মতো খারাপ নয়, যা মনে রাখা যাক, "আপনার প্রোগ্রামের অপরিজ্ঞাত আচরণ"। লেখকের কিছু আপত্তির মধ্যে রয়েছে "নান্দনিকভাবে কুরুচিপূর্ণ" এবং "খারাপ স্টাইলকে উত্সাহিত করা"। এখন আপনি বরং কি চান? খারাপ স্টাইল সহ একটি প্রোগ্রাম, বা এমন একটি যা অপরিজ্ঞাত আচরণ প্রদর্শন করে?


1
অপরিবর্তিত আচরণ নয়, বরং অবিলম্বে সমাপ্তি।
মার্ক ভ্যান লিউউয়েন

মানটি 'অপরিজ্ঞাত আচরণ' বলে। এই আচরণটি প্রায়শই সমাপ্ত হয় তবে এটি সর্বদা হয় না।
ডিজেক্লেওয়ার্থ

না, ব্যতিক্রম হ্যান্ডলিং-> [নির্দিষ্ট.আরমিষ্ট] পড়ুন- বিশেষ ক্রিয়াকলাপ (যা আমার মানক অনুলিপিতে 15.5.1, তবে এর নম্বর সম্ভবত পুরানো)।
মার্ক ভ্যান লিউউয়েন

2

প্রশ্ন: সুতরাং আমার প্রশ্নটি হ'ল - যদি কোনও ডেস্ট্রাক্টর থেকে ছুঁড়ে ফেলা ফলশ্রুতিহীন আচরণের ফলাফল করে তবে আপনি কীভাবে একজন ডেস্ট্রাক্টরের সময় ঘটে যাওয়া ত্রুটিগুলি পরিচালনা করবেন?

উত্তর: কয়েকটি বিকল্প রয়েছে:

  1. অন্য কোথাও যা চলছে তা নির্বিশেষে ব্যতিক্রমগুলি আপনার ডেস্ট্রাক্টরের বাইরে যেতে দিন। এবং এটি করার ক্ষেত্রে সতর্কতা অবলম্বন করুন (বা এমনকি ভীতুও) যে স্ট্যান্ড :: সমাপ্তি অনুসরণ করতে পারে।

  2. ব্যতিক্রম কখনও আপনার ধ্বংসকারী থেকে প্রবাহিত হতে দেবেন না। একটি লগ লিখতে হতে পারে, কিছু বড় লাল খারাপ পাঠ্য যদি আপনি পারেন।

  3. আমার fave : যদি std::uncaught_exceptionমিথ্যা ফেরত দেয় তবে আপনাকে ব্যতিক্রমগুলি প্রবাহিত হতে দিন। যদি এটি সত্য হয় তবে লগিং পদ্ধতির কাছে ফিরে যান।

তবে ডি'টারে ফেলে দেওয়া কি ভাল?

আমি উপরের বেশিরভাগের সাথে একমত যে নিক্ষেপকারী যেখানে নিক্ষিপ্ত হতে পারে সেখানে নিক্ষেপ করা সর্বোত্তমভাবে এড়ানো যায়। তবে কখনও কখনও আপনি এটি গ্রহণ করতে সেরা হন এটি ঘটতে পারে এবং এটি ভালভাবে পরিচালনা করতে পারেন। আমি উপরে 3 বেছে নেব।

কয়েকটি অদ্ভুত কেস রয়েছে যেখানে এটির ডেস্ট্রাক্টর থেকে ফেলে দেওয়া আসলে দুর্দান্ত ধারণা । "অবশ্যই চেক করুন" ত্রুটি কোডটি পছন্দ করুন। এটি একটি মান ধরণের যা কোনও ফাংশন থেকে ফিরে আসে। যদি কলারটি এতে থাকা ত্রুটি কোডটি পড়ে / পরীক্ষা করে দেখায়, প্রত্যাশিত মানটি নিঃশব্দে অবিচ্ছিন্ন করে। তবে , যদি রিটার্ন মানগুলি সুযোগের বাইরে চলে যায়, ততক্ষণে যদি ফিরে আসা ত্রুটি কোডটি না পড়ে থাকে তবে এটি তার ডেস্ট্রাক্টর থেকে কিছু ব্যতিক্রম ছুঁড়ে ফেলবে ।


4
আপনার fave এমন একটি জিনিস যা আমি সম্প্রতি চেষ্টা করেছিলাম এবং দেখা যাচ্ছে যে এটি করা উচিত নয়getw.ca/gotw/047.htm
GManNGG

1

আমি বর্তমানে নীতিটি অনুসরণ করি (তাই অনেকেই বলছেন) যে ক্লাসগুলি সক্রিয়ভাবে তাদের ধ্বংসকারীদের থেকে ব্যতিক্রম ছোঁড়া উচিত নয় বরং অপারেশনটি সম্পাদন করার জন্য একটি সর্বজনীন "ঘনিষ্ঠ" পদ্ধতি সরবরাহ করা উচিত যা ব্যর্থ হতে পারে ...

... তবে আমি বিশ্বাস করি কনটেইনার ধরণের শ্রেণীর জন্য ধ্বংসকারীরা যেমন একজন ভেক্টর, তাদের থাকা ক্লাসগুলি থেকে বাদ দেওয়া ব্যতিক্রমগুলি মাস্ক করা উচিত নয়। এই ক্ষেত্রে, আমি আসলে একটি "ফ্রি / ক্লোজ" পদ্ধতি ব্যবহার করি যা নিজেকে পুনরাবৃত্তি বলে। হ্যাঁ, আমি পুনরাবৃত্তি বলেছিলাম। এই উন্মাদনার একটি পদ্ধতি আছে। ব্যতিক্রম প্রচার সেখানে স্ট্যাকের উপর নির্ভর করে: যদি একক ব্যতিক্রম ঘটে, তবে বাকি উভয় ধ্বংসকারী এখনও চালাবেন এবং মুলতুবি ব্যতিক্রমগুলি রুটিন ফেরার পরে একবার প্রচার করবে, যা দুর্দান্ত। যদি একাধিক ব্যতিক্রম ঘটে থাকে, তবে (সংকলকের উপর নির্ভর করে) হয় সেই প্রথম ব্যতিক্রম প্রচার করবে বা প্রোগ্রামটি শেষ হবে, যা ঠিক। যদি এতগুলি ব্যতিক্রম ঘটে থাকে যে পুনরাবৃত্তি স্ট্যাকটিকে উপচে ফেলেছে তবে কিছু মারাত্মকভাবে ভুল, এবং কেউ এটির সম্পর্কে অনুসন্ধান করতে চলেছে, এটিও ঠিক। ব্যক্তিগতভাবে,

মুল বক্তব্যটি হ'ল ধারকটি নিরপেক্ষ থেকে যায় এবং তাদের ধ্বংসকারীদের থেকে ব্যতিক্রম ছোঁড়ার বিষয়ে তারা আচরণ করে বা দুর্ব্যবহার করে কি না তা সিদ্ধান্ত নিয়ে সিদ্ধান্ত নেওয়া উচিত।


1

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

সমস্যা দেখা দেয় যখন স্ট্যাক আনওয়ানডিং প্রক্রিয়া চলাকালীন কোনও ডেস্ট্রাক্টরের কাছ থেকে ব্যতিক্রম ছুঁড়ে ফেলা হয়। যদি এটি ঘটে থাকে, সংকলকটিকে এমন পরিস্থিতিতে রাখা হয়েছে যেখানে স্ট্যাক আনওয়ানডিং প্রক্রিয়া চালিয়ে যাওয়া বা নতুন ব্যতিক্রম পরিচালনা করতে হবে কিনা তা জানেনা। শেষ ফলাফলটি হ'ল আপনার প্রোগ্রামটি অবিলম্বে বন্ধ হয়ে যাবে।

ফলস্বরূপ, কর্মের সর্বোত্তম কোর্স হ'ল কেবল ডেস্ট্রাক্টরগুলিতে সম্পূর্ণ ব্যতিক্রম ব্যবহার করা থেকে বিরত থাকা। পরিবর্তে লগ ফাইলে একটি বার্তা লিখুন।


1
লগ ফাইলে একটি বার্তা লেখার ব্যতিক্রম ঘটতে পারে।
কোনার্ড

1

মার্টিন বা (উপরে) সঠিক পথে রয়েছে - আপনি রিলিজ এবং কমিট যুক্তির জন্য আলাদাভাবে স্থপতি হন।

মুক্তির জন্য:

আপনার কোনও ত্রুটি খাওয়া উচিত। আপনি মেমরি মুক্ত করছেন, সংযোগগুলি বন্ধ করছেন ইত্যাদি the সিস্টেমে আর কারও কারও কাছে আবার সেই জিনিসগুলি দেখা উচিত নয় এবং আপনি ওএসকে সংস্থানগুলি ফিরিয়ে দিচ্ছেন। যদি মনে হয় আপনার এখানে হ্যান্ডলিংয়ের সত্যিকারের ত্রুটি দরকার তবে এটি সম্ভবত আপনার অবজেক্টের মডেলের ডিজাইনের ত্রুটিগুলির একটি পরিণতি।

অঙ্গীকারের জন্য:

আপনি যেখানে একই ধরণের RAII র‍্যাপার অবজেক্ট চান তা স্টেট :: লক_গার্ডের মতো জিনিসগুলি মিউটেক্সগুলির জন্য সরবরাহ করে। তাদের সাথে আপনি সকলকে দাত্রে প্রতিশ্রুতিবদ্ধ যুক্তি রাখেন না। আপনার এটির জন্য একটি উত্সর্গীকৃত এপিআই রয়েছে, তারপরে মোড়কযুক্ত বস্তুগুলি RAII এটি তাদের ডিটারগুলিতে কমিট করবে এবং সেখানে ত্রুটিগুলি পরিচালনা করবে। মনে রাখবেন, আপনি ঠিকঠাক ঠিকঠাক একজন ডিস্ট্রাস্ট্রারে ব্যতিক্রমগুলি ধরতে পারেন; এটি তাদের মারাত্মক মারাত্মক জারি করা। এটি আপনাকে নীতি এবং বিভিন্ন ত্রুটি পরিচালনার জন্য কেবলমাত্র একটি ভিন্ন র‍্যাপার তৈরি করে (যেমন স্টডি :: অনন্য_লক বনাম স্টাড :: লক_গার্ড) বাস্তবায়ন করতে দেয় এবং নিশ্চিত করে যে আপনি কমিট যুক্তিকে কল করতে ভুলবেন না - এটি কেবলমাত্র অর্ধ-পথ এটি 1 ম স্থানে একটি ডর্টারে রাখার জন্য ন্যায্য ন্যায়সঙ্গততা।


1

সুতরাং আমার প্রশ্নটি হ'ল - যদি কোনও ডেস্ট্রাক্টর থেকে ছুঁড়ে ফেলা ফলশ্রুতিহীন আচরণের ফলাফল করে তবে আপনি কীভাবে একজন ডেস্ট্রাক্টরের সময় ঘটে যাওয়া ত্রুটিগুলি পরিচালনা করবেন?

মূল সমস্যাটি হ'ল: আপনি ব্যর্থ হতে পারবেন না । ব্যর্থ হওয়া মানে কী, সর্বোপরি? যদি কোনও ডাটাবেসে লেনদেন করা ব্যর্থ হয় এবং এটি ব্যর্থ হয় (রোলব্যাক ব্যর্থ হয়), তবে আমাদের ডেটার অখণ্ডতার কি হবে?

যেহেতু ডেস্ট্রাক্টররা উভয়ই সাধারণ এবং ব্যতিক্রমী (ব্যর্থ) পাথের জন্য আহ্বান জানায় তাই তারা নিজেরাই ব্যর্থ হতে পারে না অন্যথায় আমরা "ব্যর্থ হতে ব্যর্থ" "

এটি একটি ধারণামূলকভাবে কঠিন সমস্যা তবে প্রায়শই সমাধানটি হ'ল ব্যর্থতা ব্যর্থ হতে পারে না তা নিশ্চিত করার একটি উপায় সন্ধান করা। উদাহরণস্বরূপ, কোনও ডাটাবেস কোনও বাহ্যিক ডেটা কাঠামো বা ফাইলের প্রতিশ্রুতি দেওয়ার আগে পরিবর্তনগুলি লিখতে পারে। যদি লেনদেন ব্যর্থ হয়, তবে ফাইল / ডেটা কাঠামোটি ফেলে দেওয়া যেতে পারে। তারপরে এটি নিশ্চিত করতে হবে যে বাহ্যিক কাঠামো থেকে পরিবর্তনগুলি প্রতিশ্রুতিবদ্ধ / পারমাণবিক লেনদেন ফাইল করে যা ব্যর্থ হতে পারে না।

বাস্তববাদী সমাধানটি সম্ভবত নিশ্চিত করে নিন যে ব্যর্থতায় ব্যর্থ হওয়ার সম্ভাবনাটি জ্যোতির্বিদ্যার দিক থেকে অসম্ভব, কারণ কিছু ক্ষেত্রে ব্যর্থ হওয়ার পক্ষে অসম্ভবকে অসম্ভব করে তোলা প্রায় অসম্ভব হয়ে উঠতে পারে।

আমার সবচেয়ে সঠিক সমাধানটি হ'ল আপনার ক্লিনআপবিহীন লজিককে এমনভাবে লিখুন যাতে ক্লিনআপ যুক্তি ব্যর্থ হয় না। উদাহরণস্বরূপ, যদি আপনি কোনও বিদ্যমান ডেটা কাঠামো পরিষ্কার করার জন্য একটি নতুন ডেটা স্ট্রাকচার তৈরি করার জন্য প্রলুব্ধ হন, তবে সম্ভবত আপনি সেই সহায়িকা কাঠামোটি আগে থেকেই তৈরি করতে চাইতে পারেন যাতে আমাদের এটি আর কোনও ডেস্ট্রাক্টরের ভিতরে তৈরি করতে না হয়।

স্বীকৃতভাবেই বলা হয়ে ওঠার চেয়ে এগুলি অনেক সহজ, তবে আমি এটির পক্ষে যেতে কেবল একমাত্র সত্যই সঠিক উপায়। কখনও কখনও আমি মনে করি ব্যতিক্রমী বিষয়গুলি থেকে দূরে সাধারণ নির্বাহের পথগুলির জন্য পৃথক ডেস্ট্রাক্টর যুক্তি লেখার দক্ষতা থাকা উচিত, যেহেতু কখনও কখনও ধ্বংসকারীরা উভয়কে সামলানোর চেষ্টা করে দ্বিগুণ দায়িত্বের মতো মনে করেন (উদাহরণস্বরূপ স্কোপ গার্ডদের যা সুস্পষ্ট বরখাস্তের প্রয়োজন ; যদি তারা ব্যতিক্রমী ব্যতিক্রমী ব্যতিক্রমী ধ্বংসের পথগুলি পৃথক করতে পারে তবে তাদের এটির প্রয়োজন হবে না)।

তবুও চূড়ান্ত সমস্যাটি হ'ল আমরা ব্যর্থ হতে পারি না এবং সব ক্ষেত্রে নিখুঁতভাবে সমাধান করার পক্ষে এটি একটি শক্ত ধারণামূলক নকশা সমস্যা। আপনি যদি জটিল নিয়ন্ত্রণ কাঠামোগুলিতে খুব বেশি সংখ্যক টিনএই অবজেক্টগুলির সাথে একে অপরের সাথে আলাপচারিতা না জড়ান এবং এটির পরিবর্তে আপনার নকশাগুলি কিছুটা বাল্কিয়ার ফ্যাশনে মডেল করেন (উদাহরণস্বরূপ: পুরো কণাকে ধ্বংস করার জন্য ধ্বংসকারী দিয়ে কণা ব্যবস্থা) সিস্টেম, কণা অনুযায়ী পৃথক অ-তুচ্ছ ডেস্ট্রাক্টর নয়)। আপনি যখন এই ধরণের মোটা স্তরে আপনার নকশাগুলি মডেল করেন, তখন আপনার সাথে মোকাবিলা করার জন্য অ-তুচ্ছ ডেস্ট্রাক্টর কম থাকে এবং আপনার ডিস্ট্রাক্টর ব্যর্থ হতে না পারে তা নিশ্চিত করার জন্য প্রায়শই মেমরি / প্রসেসিং ওভারহেডের যা প্রয়োজন তা সহ্য করতে পারেন।

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

আপনি নন-তুচ্ছ ডেস্ট্রাক্টরগুলির সাথে প্রচুর টিনএজ অবজেক্টের সাথে व्यवहार করা এড়াতে এমন সমাধানগুলি প্রায়শই ঘটে থাকে। আপনি যখন কোনও জগতে জড়িয়ে পড়তে পারেন যেখানে ব্যতিক্রম-সুরক্ষা হওয়া প্রায় অসম্ভব বলে মনে হয় যখন আপনি প্রচুর টিনএজ অবজেক্টগুলিতে জড়িয়ে পড়েন যে সমস্ত অ-তুচ্ছ ডেক্টর রয়েছে।

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


1
ধ্বংস কি এখন ব্যর্থ?
কৌতূহলী

আমি মনে করি তার অর্থ এই যে ব্যর্থতার সময় ধ্বংসকারীদের ডাকা হয়েছিল, সেই ব্যর্থতাটি সাফ করতে। সুতরাং যদি কোনও সক্রিয় ব্যতিক্রমের সময় কোনও ডেস্ট্রাক্টরকে ডাকা হয়, তবে এটি আগের ব্যর্থতা থেকে সাফ করতে ব্যর্থ।
ব্যবহারকারী 2445507

0

একটি অ্যালার্ম ইভেন্ট সেট করুন। সাধারণত অ্যালার্ম ইভেন্টগুলি অবজেক্টগুলি পরিষ্কার করার সময় ব্যর্থতার বিষয়ে অবহিত করার আরও ভাল ফর্ম

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