Exception Handling (এরর এবং এক্সসেপশন হ্যান্ডলিং)

সি++ স্ট্যান্ডার্ড লাইব্রেরি (C++ Standard Library) - Computer Programming

378

C++ তে এক্সসেপশন হ্যান্ডলিং (Exception Handling) একটি প্রক্রিয়া যার মাধ্যমে প্রোগ্রামে ঘটে যাওয়া কোনো অনাকাঙ্ক্ষিত ত্রুটি বা অবস্থা মোকাবিলা করা যায়। এক্সসেপশন হ্যান্ডলিংয়ের সাহায্যে ত্রুটি ঘটলে প্রোগ্রাম বন্ধ না হয়ে বিকল্পভাবে কাজ করতে পারে। C++ এ এক্সসেপশন হ্যান্ডলিং try, catch এবং throw কিওয়ার্ডের সাহায্যে করা হয়।

এক্সসেপশন হ্যান্ডলিংয়ে try-catch ব্লক ব্যবহার করা হয় যেখানে try ব্লক এ সম্ভাব্য ত্রুটি সৃষ্টি হতে পারে এমন কোড রাখা হয় এবং catch ব্লক ত্রুটি ধরা পড়লে তার সমাধান করা হয়।


এক্সসেপশন হ্যান্ডলিংয়ের মৌলিক গঠন

এক্সসেপশন হ্যান্ডলিংয়ের মৌলিক গঠন হলো:

try {
    // সম্ভাব্য ত্রুটি সৃষ্টিকারী কোড
    throw exception; // ত্রুটি সৃষ্টির জন্য থ্রো করা হয়
} catch (type exception) {
    // ত্রুটি ধরা পড়লে তার সমাধান
}
  • try ব্লক: এখানে এমন কোড থাকে যা এক্সসেপশন সৃষ্টি করতে পারে।
  • throw: যখন ত্রুটি পাওয়া যায়, তখন throw কিওয়ার্ড দিয়ে একটি এক্সসেপশন তৈরি করা হয়।
  • catch ব্লক: এটি try ব্লক থেকে থ্রো করা এক্সসেপশন গ্রহণ করে এবং ত্রুটি হ্যান্ডেল করে।

উদাহরণ: এক্সসেপশন হ্যান্ডলিং

নিম্নলিখিত উদাহরণে, একটি সংখ্যা শূন্য দ্বারা ভাগ করার সময় এক্সসেপশন হ্যান্ডলিং করা হয়েছে।

#include <iostream>

int divide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("Division by zero error!"); // এক্সসেপশন থ্রো করা
    }
    return a / b;
}

int main() {
    int x = 10;
    int y = 0;

    try {
        int result = divide(x, y); // try ব্লকে সম্ভাব্য ত্রুটি সৃষ্টিকারী কোড
        std::cout << "Result: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cout << "Exception caught: " << e.what() << std::endl; // ত্রুটি ধরা ও প্রদর্শন
    }

    return 0;
}

ব্যাখ্যা:

  • divide ফাংশনটি দুটি সংখ্যাকে ভাগ করার চেষ্টা করে এবং b শূন্য হলে এক্সসেপশন throw করে।
  • catch ব্লকটি std::exception টাইপের এক্সসেপশন গ্রহণ করে এবং ত্রুটির বার্তা প্রদর্শন করে।

একাধিক catch ব্লক

C++ তে একাধিক catch ব্লক ব্যবহার করা যায়, যা বিভিন্ন ধরনের এক্সসেপশন হ্যান্ডেল করতে পারে।

#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw 1; // থ্রো করা হয়েছে একটি ইন্টিজার এক্সসেপশন
    } catch (int e) {
        std::cout << "Integer exception caught: " << e << std::endl;
    } catch (const std::runtime_error& e) {
        std::cout << "Runtime error: " << e.what() << std::endl;
    } catch (...) {
        std::cout << "Unknown exception caught!" << std::endl;
    }

    return 0;
}

ব্যাখ্যা:

  • এখানে প্রথম catch ব্লক int টাইপ এক্সসেপশন গ্রহণ করে।
  • দ্বিতীয় catch ব্লক std::runtime_error টাইপের এক্সসেপশন হ্যান্ডেল করে।
  • catch (...): এটি একটি সাধারণ catch ব্লক যা যেকোনো ধরনের এক্সসেপশন গ্রহণ করতে পারে।

কাস্টম এক্সসেপশন তৈরি করা

C++ এ প্রোগ্রামার নিজস্ব এক্সসেপশন তৈরি করতে পারেন কাস্টম এক্সসেপশন ক্লাস দিয়ে।

#include <iostream>
#include <exception>

class MyException : public std::exception {
public:
    const char* what() const noexcept override {
        return "Custom exception occurred!";
    }
};

int main() {
    try {
        throw MyException(); // কাস্টম এক্সসেপশন থ্রো করা
    } catch (const MyException& e) {
        std::cout << "Caught custom exception: " << e.what() << std::endl;
    }

    return 0;
}

ব্যাখ্যা:

  • MyException: এটি একটি কাস্টম এক্সসেপশন ক্লাস, যা std::exception থেকে ইনহেরিট করে।
  • what(): এটি একটি ফাংশন যা এক্সসেপশনের বার্তা প্রদান করে।

স্ট্যান্ডার্ড এক্সসেপশন ক্লাস

C++ স্ট্যান্ডার্ড লাইব্রেরিতে বিভিন্ন স্ট্যান্ডার্ড এক্সসেপশন ক্লাস রয়েছে, যেমন:

  • std::exception: এটি সব ধরনের এক্সসেপশনের জন্য বেস ক্লাস।
  • std::runtime_error: রানটাইম ত্রুটির জন্য।
  • std::logic_error: লজিক্যাল ত্রুটির জন্য।
  • std::bad_alloc: মেমোরি বরাদ্দে ত্রুটি হলে ব্যবহৃত হয়।
  • std::out_of_range: যখন ইনডেক্সের বাইরে কোনো অপারেশন হয়।

উদাহরণ:

#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::out_of_range("Index out of range!"); // স্ট্যান্ডার্ড এক্সসেপশন থ্রো করা
    } catch (const std::out_of_range& e) {
        std::cout << "Out of range error: " << e.what() << std::endl;
    }

    return 0;
}

ব্যাখ্যা:

  • std::out_of_range: এটি তখন ব্যবহৃত হয় যখন কোনো অপারেশন বৈধ সীমার বাইরে চলে যায়।

এক্সসেপশন হ্যান্ডলিংয়ের সুবিধা

  1. ত্রুটি প্রোগ্রামের মধ্যে পরিচালনা করা সহজ: এক্সসেপশন হ্যান্ডলিংয়ের মাধ্যমে প্রোগ্রামে ত্রুটির কারণে থেমে যাওয়ার পরিবর্তে ত্রুটি সহজেই হ্যান্ডেল করা যায়।
  2. কোডের পঠনযোগ্যতা বৃদ্ধি: এক্সসেপশন হ্যান্ডলিং কোডের পঠনযোগ্যতা বৃদ্ধি করে এবং ত্রুটি পরিচালনা আরও সংগঠিত করে।
  3. ত্রুটি সঠিকভাবে নির্ণয় ও প্রদর্শন: এর মাধ্যমে প্রোগ্রামে সঠিকভাবে ত্রুটি নির্ণয় করা যায় এবং প্রোগ্রাম সঠিক অবস্থায় পরিচালিত হতে থাকে।

উপসংহার

C++ তে এক্সসেপশন হ্যান্ডলিং প্রোগ্রামে ত্রুটি সঠিকভাবে পরিচালনা করতে সাহায্য করে। try, catch, এবং throw কিওয়ার্ডের মাধ্যমে এক্সসেপশন হ্যান্ডলিং করা যায়। এক্সসেপশন হ্যান্ডলিং ব্যবহার করে প্রোগ্রামকে আরও স্থিতিশীল এবং শক্তিশালী করা যায়, যা প্রোগ্রামিংয়ে ত্রুটি পরিচালনায় খুবই গুরুত্বপূর্ণ।

Content added By

Exception Handling C++ এর একটি গুরুত্বপূর্ণ বৈশিষ্ট্য, যা প্রোগ্রাম চলাকালীন সময়ে যেকোনো ধরনের অনাকাঙ্ক্ষিত বা অপ্রত্যাশিত সমস্যার সমাধানে ব্যবহৃত হয়। C++ এ Exception Handling এর মাধ্যমে প্রোগ্রামারেরা ব্যতিক্রম বা ত্রুটি মোকাবেলা করতে পারে, যা প্রোগ্রামকে সুরক্ষিত এবং কার্যকর রাখতে সাহায্য করে। C++ এর Exception Handling মেকানিজম try, catch, এবং throw কীওয়ার্ডের উপর ভিত্তি করে কাজ করে।


Exception Handling এর মৌলিক ধারণা

Exception হলো এমন একটি পরিস্থিতি যা প্রোগ্রাম চলাকালীন ত্রুটি বা ব্যতিক্রম ঘটায়, যেমন বিভাজ্য শূন্য দ্বারা ভাগ (division by zero), ফাইল খোলা না যাওয়া, মেমোরি এলোকেশন ব্যর্থ হওয়া ইত্যাদি। C++ এর Exception Handling মেকানিজম এই ত্রুটিগুলোর সমাধান করার একটি কাঠামো প্রদান করে, যাতে প্রোগ্রাম ব্যতিক্রম ঘটলেও সম্পূর্ণভাবে বন্ধ না হয়।

  • try: try ব্লকের মধ্যে সেই কোড রাখা হয়, যেটিতে ব্যতিক্রম ঘটার সম্ভাবনা থাকে।
  • catch: catch ব্লকটি সেই ব্যতিক্রম ধরতে এবং সেই অনুযায়ী কাজ করতে ব্যবহৃত হয়।
  • throw: throw কীওয়ার্ড ব্যবহার করে ব্যতিক্রম ঘটানো হয়, যা catch ব্লকে ধরা যায়।

Exception Handling এর মৌলিক গঠন

try {
    // এমন কোড যা ত্রুটি ঘটাতে পারে
} catch (exception_type variable) {
    // ত্রুটি সমাধানের জন্য কোড
}

এখানে, try ব্লকের ভেতরের কোডে যদি কোনো ব্যতিক্রম ঘটে, তবে তা catch ব্লকে ধরা হবে। catch ব্লকের প্যারামিটার exception_type সেই ব্যতিক্রমের ধরনের জন্য নির্ধারিত।


উদাহরণ: ব্যতিক্রম ঘটানো এবং ধরা

#include <iostream>

int main() {
    int a = 10, b = 0;
    try {
        if (b == 0) {
            throw "Division by zero error!"; // ব্যতিক্রম ঘটানো
        }
        std::cout << "Result: " << a / b << std::endl;
    } catch (const char* e) { // ব্যতিক্রম ধরা
        std::cerr << "Exception: " << e << std::endl;
    }
    return 0;
}

আউটপুট:

Exception: Division by zero error!

এখানে b == 0 হলে throw কীওয়ার্ড ব্যবহার করে একটি ব্যতিক্রম ঘটানো হয়েছে। catch ব্লক সেই ব্যতিক্রম ধরেছে এবং Division by zero error! মেসেজ প্রদর্শন করেছে।


একাধিক catch ব্লক ব্যবহার

C++ এ একই try ব্লকের সাথে একাধিক catch ব্লক থাকতে পারে। এটি বিভিন্ন ধরনের ব্যতিক্রম ধরতে সহায়ক।

#include <iostream>

int main() {
    try {
        int x;
        std::cout << "Enter a number: ";
        std::cin >> x;

        if (x < 0) throw std::runtime_error("Negative number error!");
        else if (x == 0) throw 0;
        else if (x > 100) throw 1.0;

        std::cout << "You entered: " << x << std::endl;

    } catch (const std::runtime_error& e) {
        std::cerr << "Runtime error: " << e.what() << std::endl;
    } catch (int) {
        std::cerr << "Exception: Zero input error!" << std::endl;
    } catch (double) {
        std::cerr << "Exception: Input greater than 100!" << std::endl;
    }
    return 0;
}

আউটপুট:

Enter a number: -5
Runtime error: Negative number error!

এখানে একাধিক catch ব্লক ব্যবহৃত হয়েছে এবং প্রতিটি আলাদা ধরনের ব্যতিক্রম ধরার জন্য কাজ করেছে।


কাস্টম Exception ক্লাস তৈরি

C++ এ প্রয়োজন অনুযায়ী কাস্টম Exception ক্লাস তৈরি করা যায়। কাস্টম Exception ক্লাস ব্যবহার করে নির্দিষ্ট ত্রুটির জন্য আরও বিস্তারিত ব্যতিক্রম হ্যান্ডলিং তৈরি করা সম্ভব।

উদাহরণ: কাস্টম Exception ক্লাস

#include <iostream>
#include <stdexcept>

class DivideByZeroException : public std::runtime_error {
public:
    DivideByZeroException() : std::runtime_error("Division by zero error!") {}
};

int divide(int a, int b) {
    if (b == 0) {
        throw DivideByZeroException(); // কাস্টম ব্যতিক্রম ঘটানো
    }
    return a / b;
}

int main() {
    try {
        std::cout << "Result: " << divide(10, 0) << std::endl;
    } catch (const DivideByZeroException& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    return 0;
}

আউটপুট:

Exception: Division by zero error!

এখানে, DivideByZeroException একটি কাস্টম ব্যতিক্রম ক্লাস যা std::runtime_error থেকে অবিরত হয়েছে। divide ফাংশন ব্যতিক্রম ঘটালে main ফাংশনের catch ব্লক সেই ব্যতিক্রম ধরে এবং মেসেজ প্রদর্শন করে।


ব্যতিক্রম প্রোপাগেশন (Exception Propagation)

C++ এ ব্যতিক্রম এক ফাংশন থেকে অন্য ফাংশনে প্রেরণ করা যেতে পারে। যখন একটি ফাংশনে ব্যতিক্রম ঘটানো হয় এবং সেটি যদি ব্যতিক্রম হ্যান্ডেল না করে, তবে ব্যতিক্রমটি তার কলিং ফাংশনে প্রেরিত হয়। একে Exception Propagation বলে।

#include <iostream>

void func2() {
    throw "Error occurred in func2"; // ব্যতিক্রম ঘটানো
}

void func1() {
    func2(); // ব্যতিক্রমটি func1 এ আসবে
}

int main() {
    try {
        func1();
    } catch (const char* e) {
        std::cerr << "Caught Exception: " << e << std::endl;
    }
    return 0;
}

আউটপুট:

Caught Exception: Error occurred in func2

এখানে func2 তে ব্যতিক্রম ঘটেছে, যা func1 এ প্রেরিত হয়েছে এবং অবশেষে main এ ধরা হয়েছে।


উপসংহার

C++ এ Exception Handling প্রোগ্রামের নিরবচ্ছিন্ন কার্যক্রম নিশ্চিত করতে গুরুত্বপূর্ণ। এটি ত্রুটি বা ব্যতিক্রম ঘটলে প্রোগ্রামকে বন্ধ না করে ব্যতিক্রমটি ধরতে এবং সমাধান করতে সহায়ক।

  • try ব্লক ব্যবহার করে ব্যতিক্রম হ্যান্ডলিং শুরু করা হয়।
  • throw ব্যবহার করে ব্যতিক্রম ঘটানো হয়।
  • catch ব্লক ব্যবহার করে ব্যতিক্রম হ্যান্ডেল করা হয়।

Exception Handling ব্যবহারে প্রোগ্রামের নির্ভরযোগ্যতা বৃদ্ধি পায় এবং এটি প্রোগ্রামকে আরও কার্যকর ও সুরক্ষিত রাখে।

Content added By

C++-এ try, catch, এবং throw ব্যবহার করে exception handling (ত্রুটি পরিচালনা) করা হয়। Exception handling একটি শক্তিশালী প্রোগ্রামিং কৌশল যা প্রোগ্রামে ত্রুটি বা ব্যতিক্রমের ঘটনা মোকাবেলা করতে ব্যবহৃত হয়, যেমন যদি কোনো নির্ধারিত শর্ত পূর্ণ না হয়, ফাইল না খোলা যায়, ডিভাইস থেকে ডেটা পড়া না যায়, বা কোনো অস্বাভাবিক পরিস্থিতি তৈরি হয়। throw ব্যবহার করে ত্রুটি সৃষ্টি করা হয়, এবং try-catch ব্লকগুলি সেই ত্রুটিকে ক্যাচ (ধরা) এবং পরিচালনা করতে ব্যবহৃত হয়।

1. throw: Exception উত্পন্ন করা

throw কিওয়ার্ডটি ব্যবহার করা হয় ত্রুটি বা ব্যতিক্রম সৃষ্টির জন্য। এটি একটি exception object তৈরি করে এবং এটি try ব্লকে পাঠানো হয়।

Syntax:

throw expression;
  • expression: এটি যে কোনও অবজেক্ট হতে পারে, যা exception হিসেবে কাজ করবে (যেমন একটি int, std::exception অবজেক্ট ইত্যাদি)।

উদাহরণ:

#include <iostream>

void checkNumber(int num) {
    if (num < 0) {
        throw "Negative number exception!"; // exception throw করা
    }
}

int main() {
    try {
        checkNumber(-1);  // এখানে ত্রুটি ঘটবে
    }
    catch (const char* msg) {
        std::cout << "Caught exception: " << msg << std::endl;  // exception ধরা হয়েছে
    }

    return 0;
}

আউটপুট:

Caught exception: Negative number exception!

এখানে, throw কিওয়ার্ডের মাধ্যমে "Negative number exception!" একটি exception হিসেবে তৈরি করা হয়েছে এবং catch ব্লক তা ধরেছে এবং প্রিন্ট করেছে।


2. try: Exception চেক করা

try ব্লক একটি অংশ যেখানে প্রোগ্রামটি এমন কিছু কোড চালায় যেটি ত্রুটি সৃষ্টি করতে পারে। যদি কোনো ত্রুটি ঘটে, তাহলে catch ব্লক সেই exception ধরবে।

Syntax:

try {
    // কোড যা exception সৃষ্টি করতে পারে
}
catch (exception_type1 e1) {
    // exception_type1 ধরা হলে এটি কার্যকর হবে
}
catch (exception_type2 e2) {
    // exception_type2 ধরা হলে এটি কার্যকর হবে
}

উদাহরণ:

#include <iostream>

void division(int a, int b) {
    if (b == 0) {
        throw "Division by zero error!";  // যদি b 0 হয়, তাহলে exception throw হবে
    }
    std::cout << "Result: " << a / b << std::endl;
}

int main() {
    try {
        division(10, 0);  // এখানে division() ত্রুটি ঘটাবে
    }
    catch (const char* msg) {
        std::cout << "Caught exception: " << msg << std::endl;  // exception catch করা হবে
    }

    return 0;
}

আউটপুট:

Caught exception: Division by zero error!

এখানে, try ব্লকটি কোড চালানোর চেষ্টা করছে, কিন্তু যখন b == 0, তখন throw কিওয়ার্ডের মাধ্যমে একটি exception তৈরি হচ্ছে। catch ব্লক তা ধরছে এবং ত্রুটির বার্তা প্রিন্ট করছে।


3. catch: Exception Handling

catch ব্লকটি try ব্লক থেকে কোনো exception সৃষ্টির পরে সেই exception ধরার জন্য ব্যবহৃত হয়। এক বা একাধিক catch ব্লক থাকতে পারে যা বিভিন্ন ধরনের exception ধরতে পারে।

Syntax:

try {
    // কিছু কোড
}
catch (type1 e1) {
    // type1 exception handle করা
}
catch (type2 e2) {
    // type2 exception handle করা
}

উদাহরণ:

#include <iostream>

void processNumber(int num) {
    if (num == 0) {
        throw std::invalid_argument("Invalid argument: number cannot be zero.");
    } else if (num < 0) {
        throw std::out_of_range("Out of range: number cannot be negative.");
    }
    std::cout << "Processing number: " << num << std::endl;
}

int main() {
    try {
        processNumber(-5);  // এটি "out_of_range" exception throw করবে
    }
    catch (const std::invalid_argument& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
    catch (const std::out_of_range& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
    catch (...) {
        std::cout << "Caught unknown exception." << std::endl;
    }

    return 0;
}

আউটপুট:

Caught exception: Out of range: number cannot be negative.

এখানে, catch ব্লক দুটি আলাদা exception টাইপ (std::invalid_argument এবং std::out_of_range) ধরতে সক্ষম এবং যে exception ঘটবে তা সঠিকভাবে ধরবে।


4. Exception Classes

C++ তে std::exception হলো সকল exception এর মূল ক্লাস, এবং অন্যান্য exception ক্লাসগুলো এর সাথে ডেরাইভড (উপজাত) থাকে। আপনি নিজের exception ক্লাসও তৈরি করতে পারেন যা std::exception বা তার ডেরাইভড ক্লাস থেকে উত্তরাধিকারী হতে পারে।

উদাহরণ: Custom Exception Class

#include <iostream>
#include <stdexcept>

class MyException : public std::exception {
public:
    const char* what() const noexcept override {
        return "This is a custom exception.";
    }
};

int main() {
    try {
        throw MyException();
    }
    catch (const MyException& e) {
        std::cout << "Caught custom exception: " << e.what() << std::endl;
    }

    return 0;
}

আউটপুট:

Caught custom exception: This is a custom exception.

এখানে, MyException একটি কাস্টম exception ক্লাস, যা std::exception থেকে উত্তরাধিকারসূত্রে এসেছে এবং what() মেথডটি পুনরায় সংজ্ঞায়িত করা হয়েছে।


5. Multiple Catch Blocks

একই try ব্লক থেকে একাধিক ধরনের exception ধরা যায়, এবং catch ব্লকগুলিকে নির্দিষ্ট exception টাইপ অনুযায়ী সাজানো যেতে পারে।

উদাহরণ:

#include <iostream>
#include <exception>

void throwExceptions(int choice) {
    if (choice == 1) {
        throw std::invalid_argument("Invalid argument exception.");
    } else if (choice == 2) {
        throw std::out_of_range("Out of range exception.");
    } else {
        throw std::exception();
    }
}

int main() {
    try {
        throwExceptions(2);  // এই ক্ষেত্রে out_of_range exception হবে
    }
    catch (const std::invalid_argument& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
    catch (const std::out_of_range& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
    catch (const std::exception& e) {
        std::cout << "Caught unknown exception: " << e.what() << std::endl;
    }

    return 0;
}

আউটপুট:

Caught exception: Out of range exception.

এখানে, যদি choice == 2 হয়, তবে std::out_of_range exception ধরা হবে।


উপসংহার

  • throw: একটি exception তৈরি করতে ব্যবহৃত হয় এবং এটি try ব্লকে পাঠানো হয়।
  • try: এই ব্লকটি কোডকে এমনভাবে চালায় যেখানে exception ঘটতে পারে।
  • catch: exception ধরা এবং এর সাথে কাজ করার জন্য ব্যবহৃত হয়। এটি এক বা একাধিক catch ব্লক দ্বারা handle করা যেতে পারে।

Exception handling C++ প্রোগ্রামিংয়ে গুরুত্বপূর্ণ, কারণ এটি প্রোগ্রামের ত্রুটি বা ব্যতিক্রমের পরিস্থিতি মোকাবেলা করতে সাহায্য করে, বিশেষত যখন প্রোগ্রামে অপ্রত্যাশিত ত্রুটি বা ভুল ঘটতে পারে।

Content added By

C++ স্ট্যান্ডার্ড লাইব্রেরিতে বিভিন্ন ধরনের exceptions রয়েছে যা প্রোগ্রামিংয়ের সময় ত্রুটি (error) মোকাবেলা করতে ব্যবহৃত হয়। এই exceptions-গুলি std::exception এর মাধ্যমে প্রাপ্ত হয় এবং তাদের মধ্যে std::runtime_error, std::logic_error অন্যতম। প্রতিটি exception ক্লাস একটি নির্দিষ্ট ধরনের ত্রুটি নির্দেশ করে এবং সঠিকভাবে ব্যবহার করা হলে প্রোগ্রাম আরও নির্ভরযোগ্য এবং নিরাপদ হয়।

১. std::exception

std::exception হল C++ স্ট্যান্ডার্ড লাইব্রেরির সবচেয়ে সাধারণ exception ক্লাস, এবং এটি সব ধরনের exception এর মূল ক্লাস। এর মাধ্যমে আমরা ত্রুটি সম্পর্কিত বিস্তারিত তথ্য পেতে পারি। std::exception ক্লাসে what() নামক একটি মেথড রয়েছে, যা ত্রুটির বর্ণনা সরবরাহ করে।

উদাহরণ:

#include <iostream>
#include <exception>

int main() {
    try {
        throw std::exception();  // সাধারণ exception ফেলে দেওয়া
    } catch (const std::exception& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
    return 0;
}

আউটপুট:

Caught exception: std::exception

এখানে, std::exception ত্রুটির বর্ণনা প্রদান করেছে। তবে এটি একটি সাধারণ ত্রুটি, তাই ত্রুটির আরও নির্দিষ্ট কারণ জানতে std::runtime_error বা std::logic_error ব্যবহার করা হয়।


২. std::runtime_error

std::runtime_error হল std::exception ক্লাস থেকে উত্তরাধিকার সূত্রে প্রাপ্ত একটি বিশেষ ক্লাস যা রানটাইম (execution time) ত্রুটির জন্য ব্যবহৃত হয়। এই ত্রুটির মধ্যে এমন ধরনের ত্রুটি থাকে যা প্রোগ্রামের চলমান অবস্থায় ঘটতে পারে, যেমন অবৈধ ইনপুট, ফাইল খোলার সময় ত্রুটি, বা ভুল হিসাব

std::runtime_error-এর কনস্ট্রাক্টরে একটি বর্ণনা পাস করা যায় যা what() ফাংশনের মাধ্যমে ফেরত দেওয়া হয়।

উদাহরণ:

#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::runtime_error("Something went wrong during runtime!");  // runtime_error ফেলা
    } catch (const std::runtime_error& e) {
        std::cout << "Caught runtime_error: " << e.what() << std::endl;
    }
    return 0;
}

আউটপুট:

Caught runtime_error: Something went wrong during runtime!

এখানে std::runtime_error ত্রুটির সাথে একটি কাস্টম মেসেজ প্রদান করা হয়েছে, যা what() মেথডের মাধ্যমে প্রদর্শিত হয়েছে।


৩. std::logic_error

std::logic_error একটি exception ক্লাস যা লজিক্যাল ত্রুটি নির্দেশ করে। এটি এমন ত্রুটি যা সাধারণত অকল্পনীয় বা অযৌক্তিক পরিস্থিতি সৃষ্টি হয়, যেমন ভুল ক্যালকুলেশন বা অকার্যকর স্টেটমেন্ট।

যখন এমন কোনো ত্রুটি ঘটে যা কোডের লজিকের কারণে বা ভুল ডেটা ব্যবহারের কারণে হয়ে থাকে, তখন std::logic_error ব্যবহার করা হয়। এর মধ্যে অনেক সাবক্লাসও রয়েছে, যেমন std::invalid_argument, std::out_of_range, std::domain_error ইত্যাদি।

উদাহরণ:

#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::logic_error("Logic error encountered!");  // logic_error ফেলা
    } catch (const std::logic_error& e) {
        std::cout << "Caught logic_error: " << e.what() << std::endl;
    }
    return 0;
}

আউটপুট:

Caught logic_error: Logic error encountered!

এখানে, std::logic_error একটি ভুলের কারণে ফেলা হয়েছে, যা লজিক্যাল ত্রুটি হিসেবে চিহ্নিত করা হয়েছে।


৪. স্ট্যান্ডার্ড Exceptions এর অন্যান্য ক্লাস

C++ স্ট্যান্ডার্ড লাইব্রেরিতে std::exception এর অনেক অন্যান্য সাবক্লাস রয়েছে যা নির্দিষ্ট ধরনের ত্রুটি পরিচালনা করতে ব্যবহৃত হয়:

  • std::invalid_argument: অকার্যকর আর্গুমেন্ট (যেমন ফাংশনে ভুল ইনপুট দেওয়া)।
  • std::out_of_range: কোনো অ্যারে বা কনটেইনারের বাইরে যাওয়া।
  • std::overflow_error: অতিরিক্ত মান গণনা (overflow)।
  • std::underflow_error: কম মান গণনা (underflow)।
  • std::bad_alloc: মেমরি অ্যালোকেশন সমস্যা (যখন নতুন মেমরি অ্যাক্সেস করা সম্ভব হয় না)।
  • std::domain_error: একটি অকার্যকর ডোমেইন হিসেবে ইনপুট দেয়া (যেমন, নেগেটিভ নাম্বারের স্কয়ার রুট নেওয়া)।

উদাহরণ (অতিরিক্ত স্ট্যান্ডার্ড exceptions):

#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::invalid_argument("Invalid argument provided!");  // invalid_argument ফেলা
    } catch (const std::invalid_argument& e) {
        std::cout << "Caught invalid_argument: " << e.what() << std::endl;
    }

    try {
        throw std::out_of_range("Index is out of range!");  // out_of_range ফেলা
    } catch (const std::out_of_range& e) {
        std::cout << "Caught out_of_range: " << e.what() << std::endl;
    }

    return 0;
}

আউটপুট:

Caught invalid_argument: Invalid argument provided!
Caught out_of_range: Index is out of range!

Exception Handling Flow

  1. Throwing Exceptions: যখন কোনো ত্রুটি ঘটবে, throw কিওয়ার্ডের মাধ্যমে একটি exception উত্থাপন করা হয়।
  2. Catching Exceptions: try ব্লকে রক্ষা করা কোডের মধ্যে exception হলে, সেই exception কে catch ব্লক দ্বারা ধরা হয় এবং সংশ্লিষ্ট সমাধান নেওয়া হয়।
  3. what() Method: what() মেথডটি exception সম্পর্কিত ত্রুটির বর্ণনা প্রদান করে।

উপসংহার

  • std::exception: সব ধরনের exceptions এর মূল ক্লাস। সাধারণভাবে ব্যবহৃত হয়, এবং এতে একটি what() মেথড রয়েছে যা ত্রুটির বর্ণনা দেয়।
  • std::runtime_error: রানটাইম ত্রুটি নির্দেশ করে এবং এটির কনস্ট্রাক্টরে একটি ত্রুটির বর্ণনা যুক্ত করা হয়।
  • std::logic_error: লজিক্যাল ত্রুটি নির্দেশ করে, যখন কোডের অযৌক্তিক আচরণ বা ভুল যুক্তি ঘটে।

স্ট্যান্ডার্ড exceptions গুলি C++-এ ত্রুটির সঠিক ব্যাখ্যা এবং সমাধান খুঁজে বের করার জন্য একটি শক্তিশালী হাতিয়ার।

Content added By

Exception Safety এবং Stack Unwinding সি++ প্রোগ্রামিংয়ে গুরুত্বপূর্ণ ধারণা যা প্রোগ্রামের ত্রুটি ব্যবস্থাপনা এবং নিরাপত্তা নিশ্চিত করে। এগুলো নিশ্চিত করে যে যখন একটি এক্সসেপশন ঘটে তখন প্রোগ্রাম ক্র্যাশ না করে সঠিকভাবে সাফ এবং রিসোর্সগুলি মুক্ত হয়।

১. Exception Safety

Exception Safety হল এমন একটি ধারণা যা প্রোগ্রাম বা ফাংশনগুলোকে এমনভাবে ডিজাইন করে যাতে এক্সসেপশন ঘটলে, সিস্টেমের স্থিতিশীলতা এবং মেমরি নিরাপত্তা নিশ্চিত থাকে। এটি নিশ্চিত করে যে একটি এক্সসেপশন ঘটলেও কোনও ডেটা ক্ষতি বা মেমরি লিক হবে না, এবং প্রোগ্রামটি সঠিকভাবে চলতে থাকবে।

সি++ এ তিনটি স্তরের exception safety আছে:

  1. No-throw guarantee (No-throw safety): যদি কোনো এক্সসেপশন ঘটে, তবে ফাংশন বা কোড কোনো রকম মিউটেশন বা পরিবর্তন করবে না এবং কোনো রিসোর্স মুক্ত হবে না। এটি সবচেয়ে নিরাপদ স্তর।
  2. Basic guarantee (Basic safety): এক্সসেপশন ঘটলেও প্রোগ্রামের অবস্থা অপরিবর্তিত থাকবে এবং কোন অবাঞ্ছিত পার্শ্বপ্রতিক্রিয়া হবে না। তবে, কিছু রিসোর্স মুক্ত করা না হতে পারে।
  3. Strong guarantee (Strong safety): এক্সসেপশন ঘটলে প্রোগ্রাম আগের অবস্থায় ফিরে যাবে, অর্থাৎ প্রোগ্রামটি পুরোপুরি রোলব্যাক হয়ে যাবে। এক্সসেপশন ঘটলে কোনও পরিবর্তন হবে না এবং অবস্থা অপরিবর্তিত থাকবে।

উদাহরণ: Exception Safety

#include <iostream>
#include <vector>

class MyClass {
public:
    MyClass(int size) : data(size, 0) {}

    // নিরাপদ ফাংশন যা কপি অপারেশন করে
    void set(int index, int value) {
        if (index < 0 || index >= data.size()) {
            throw std::out_of_range("Index out of range");
        }
        data[index] = value;
    }

private:
    std::vector<int> data;
};

int main() {
    try {
        MyClass obj(10);
        obj.set(5, 100);  // সঠিক কল
        obj.set(20, 200); // এরর, এক্সসেপশন হবে
    }
    catch (const std::exception& e) {
        std::cout << "Exception caught: " << e.what() << std::endl;
    }

    return 0;
}

এখানে, set ফাংশনে যদি ইনডেক্স ভুল হয়, তাহলে একটি std::out_of_range এক্সসেপশন ঘটে। এই ফাংশনে Basic guarantee রয়েছে, অর্থাৎ এক্সসেপশন ঘটলেও, কোন ডেটা পরিবর্তন হবে না এবং সিস্টেমের অবস্থা অপরিবর্তিত থাকবে।


২. Stack Unwinding

Stack Unwinding হল সেই প্রক্রিয়া যা ঘটে যখন একটি এক্সসেপশন তৈরি হয় এবং স্ট্যাকের উপর থেকে সমস্ত ফাংশন কল ফিরে আসে। যখন এক্সসেপশন ঘটে, সি++ এ প্রোগ্রামটি "stack unwinding" প্রক্রিয়া শুরু করে, যা প্রতিটি ফাংশন কলের ক্ষেত্রে স্থানীয় স্ট্যাক ভেরিয়েবলগুলোকে ধ্বংস করে এবং তারপরে আগের ফাংশন কলের স্ট্যাক ফ্রেমে ফিরে যায়। এটি এক্সসেপশন ঘটলে ফাংশনগুলোর মধ্যে নির্দিষ্ট কাজ সম্পন্ন করতে সাহায্য করে, যেমন রিসোর্সগুলি মুক্ত করা (যেমন ডেস্ট্রাক্টর কল করা)।

Stack Unwinding এর মাধ্যমে:

  • ডেস্ট্রাক্টর কল করা হয়, যা স্ট্যাক-ভিত্তিক রিসোর্সগুলি সঠিকভাবে মুক্ত করে।
  • কোন রিসোর্স বা অবস্থা ক্ষতিগ্রস্ত না হয়ে প্রোগ্রাম চলতে থাকে।

উদাহরণ: Stack Unwinding

#include <iostream>

class MyClass {
public:
    MyClass() { std::cout << "MyClass Constructor" << std::endl; }
    ~MyClass() { std::cout << "MyClass Destructor" << std::endl; }

    void doSomething() {
        std::cout << "Doing something!" << std::endl;
        throw std::runtime_error("Error occurred");
    }
};

void testFunction() {
    MyClass obj;
    obj.doSomething(); // এক্সসেপশন হবে
}

int main() {
    try {
        testFunction();
    }
    catch (const std::exception& e) {
        std::cout << "Exception caught: " << e.what() << std::endl;
    }

    return 0;
}

এখানে, testFunction ফাংশনে obj.doSomething() কলের সময় একটি std::runtime_error এক্সসেপশন ঘটবে। এক্সসেপশন ঘটলে, MyClass এর ডেস্ট্রাক্টরটি কল হবে, কারণ এটি স্ট্যাক-ভিত্তিক একটি অবজেক্ট, এবং তাই stack unwinding এর মাধ্যমে এটি সঠিকভাবে পরিষ্কার হয়ে যাবে।

আউটপুট হবে:

MyClass Constructor
Doing something!
MyClass Destructor
Exception caught: Error occurred

এখানে, MyClass এর কনস্ট্রাক্টর প্রথমে কল হয়, তারপর doSomething কল করা হয়, এবং এক্সসেপশন ঘটলে, MyClass এর ডেস্ট্রাক্টর কল হয় (stack unwinding), তারপর catch ব্লক ত্রুটির বার্তা দেখায়।


Stack Unwinding এবং Exception Safety এর সম্পর্ক

যখন এক্সসেপশন ঘটে এবং stack unwinding ঘটে, সি++ নিশ্চিত করে যে:

  1. অ্যাক্সেসযোগ্য রিসোর্সগুলি মুক্ত করা হবে (যেমন ডেস্ট্রাক্টর কল করা)।
  2. সংশ্লিষ্ট ফাংশন কলগুলির স্ট্যাক ফ্রেমে থাকা ডেটা সঠিকভাবে ধ্বংস হবে
  3. প্রোগ্রামটি সঠিকভাবে পুনরুদ্ধার হবে (যদিও এক্সসেপশন ঘটেছে) যদি সঠিক exception safety গ্যারান্টি অনুসরণ করা হয়।

সারাংশ

  • Exception Safety: এটি ফাংশনগুলির জন্য এক্সসেপশন ঘটলে তাদের নিরাপদভাবে কার্যক্রম চালিয়ে যাওয়া এবং সিস্টেমের অবস্থা অপরিবর্তিত রাখার গ্যারান্টি প্রদান করে।
  • Stack Unwinding: যখন এক্সসেপশন ঘটে, সি++ স্ট্যাকের উপর থেকে প্রতিটি ফাংশন কল ধ্বংস করে এবং সংশ্লিষ্ট ডেস্ট্রাক্টরগুলিকে কল করে, যাতে সমস্ত রিসোর্স মুক্ত হয়।

Stack unwinding এবং exception safety এর সঠিক ব্যবস্থাপনা সি++ প্রোগ্রামগুলিকে নিরাপদ, দক্ষ এবং স্থিতিশীল রাখে।

Content added By
Promotion

Are you sure to start over?

Loading...