معالجة الأخطاء في C++: try/catch من الألف إلى الياء – دليل شامل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا تعتبر معالجة الأخطاء أساس الكود الموثوق في C++



أي برنامج يتفاعل مع العالم الخارجي (ملفات، شبكة، إدخال المستخدم) سيواجه حتماً حالات استثنائية. في لغة C++، تُعد آلية try/catch الأداة الرئيسية لإدارة هذه الحالات بأناقة وتحكم. في هذه المقالة، سنشرح معالجة الأخطاء في C++ بدءاً من الهياكل الأساسية وصولاً إلى التقنيات المتقدمة، بما في ذلك أفضل الممارسات والمزالق المحتملة.



1. الأساسيات: try, catch و throw



آلية الاستثناءات في C++ تُبنى على ثلاث كلمات مفتاحية: try و catch و throw.



1.1. كتلة try و catch

كتلة try تحتوي على الكود الذي قد يُلقي استثناءً. كتلة catch تلتقط هذا الاستثناء وتعالجه.



#include <iostream>#include <stdexcept>

int main() { try { // كود قد يسبب خطأ int age = -5; if (age < 0) { throw std::invalid_argument("العمر لا يمكن أن يكون سالباً"); } std::cout << "العمر: " << age << std::endl; } catch (const std::invalid_argument& e) { std::cerr << "خطأ: " << e.what() << std::endl; } return 0;}


1.2. أنواع الاستثناءات

في C++، يمكن إلقاء استثناءات من أي نوع: أرقام، نصوص، كائنات فئات. ومع ذلك، يُوصى باستخدام فئات الاستثناءات القياسية من <stdexcept> أو إنشاء فئات خاصة بنا موروثة من std::exception.



  • الاستثناءات القياسية: std::runtime_error، std::logic_error، std::out_of_range وغيرها.
  • الاستثناءات المخصصة: تُنشأ عن طريق الوراثة من std::exception.


class MyException : public std::exception {public:    const char* what() const noexcept override {        return "الاستثناء الخاص بي";    }};


1.3. كتل catch متعددة

يمكنك التقاط أنواع مختلفة من الاستثناءات في كتل catch منفصلة. الترتيب مهم: يجب أن تأتي الاستثناءات الأكثر تحديداً أولاً.



try {    // كود} catch (const std::invalid_argument& e) {    // معالجة invalid_argument} catch (const std::exception& e) {    // معالجة جميع الاستثناءات الأخرى من std} catch (...) {    // catch-all: يلتقط كل ما لم يُلتقط أعلاه}


2. تقنيات متقدمة: تفكيك المكدس و RAII



2.1. تفكيك المكدس (Stack Unwinding)

عند إلقاء استثناء، تقوم C++ تلقائياً بتدمير جميع الكائنات المحلية في المسار من نقطة throw إلى catch المناسب. تُسمى هذه العملية تفكيك المكدس. وهي تضمن استدعاء المدمرات لجميع الكائنات التي تم إنشاؤها في كتل try.



class Resource {public:    Resource() { std::cout << "تم إنشاء المورد"; }    ~Resource() { std::cout << "تم تدمير المورد"; }};

void riskyFunction() { Resource res; throw std::runtime_error("حدث خطأ ما");}

int main() { try { riskyFunction(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } // الإخراج: تم إنشاء المورد -> تم تدمير المورد -> حدث خطأ ما}


2.2. RAII (اكتساب الموارد هو التهيئة)

RAII هي إحدى الركائز الأساسية في C++ وترتبط ارتباطاً وثيقاً بمعالجة الأخطاء. الفكرة: إدارة الموارد (الذاكرة، الملفات، كائنات المزامنة) ترتبط بعمر الكائن. المدمر يحرر المورد تلقائياً، حتى في حالة الاستثناء.



  • المؤشرات الذكية: std::unique_ptr، std::shared_ptr

المدونات

توصيات الكتب