كيف يمكنني التقاط جميع أنواع الاستثناءات في كتلة التقاط واحدة؟

StackOverflow https://stackoverflow.com/questions/55859

سؤال

في C++، أحاول التقاط جميع أنواع الاستثناءات في زر واحد (مثل catch(Exception) شركة#).كيف يتم ذلك؟والأكثر من ذلك، كيف يمكن للمرء التقاط استثناءات القسمة على صفر؟

هل كانت مفيدة؟

المحلول

catch (...)
{
   // Handle exceptions not covered.
}

اعتبارات هامة:

  • الطريقة الأفضل هي اكتشاف أنواع معينة من الاستثناءات التي يمكنك التعافي منها بالفعل بدلاً من جميع الاستثناءات المحتملة.
  • سوف يلتقط التقاط (...) أيضًا بعض الاستثناءات الخطيرة على مستوى النظام (تختلف اعتمادًا على المترجم) والتي لن تتمكن من استردادها بشكل موثوق.إن الإمساك بها بهذه الطريقة ثم ابتلاعها والاستمرار فيها قد يسبب المزيد من المشاكل الخطيرة في برنامجك.
  • اعتمادًا على السياق الخاص بك، قد يكون من المقبول استخدام الصيد (...)، بشرط إعادة طرح الاستثناء.في هذه الحالة، يمكنك تسجيل كافة معلومات الحالة المحلية المفيدة ثم إعادة طرح الاستثناء للسماح له بالانتشار.ومع ذلك يجب عليك أن تقرأ على نمط راي إذا اخترت هذا الطريق.

نصائح أخرى

أنت لا تريد أن تستخدم الصيد (...) (أي.التقط مع علامة الحذف) إلا إذا كنت حقًا، بالتأكيد، في حاجة إلى ذلك.

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

ومن الناحية الفنية، نعم، يمكنك أيضًا إجراء القسمة على الصفر (سيتعين عليك استخدام "StackOverflow" للقيام بذلك)، ولكن يجب عليك حقًا تجنب إجراء مثل هذه القسمة في المقام الأول.

بدلاً من ذلك، قم بما يلي:

  • إذا كنت تعرف بالفعل نوع الاستثناء (الاستثناءات) الذي تتوقعه، فالتقط تلك الأنواع وليس أكثر، و
  • إذا كنت بحاجة إلى طرح الاستثناءات بنفسك، وتحتاج إلى التقاط جميع الاستثناءات التي ستطرحها، فاجعل هذه الاستثناءات مشتقة من std::exception (كما اقترح آدم بيرس) والتقط ذلك.

إذا كنت تستخدم نظام التشغيل Windows وتحتاج إلى معالجة أخطاء مثل القسمة على صفر وانتهاك الوصول، فيمكنك استخدام مترجم الاستثناءات المنظمة.ومن ثم داخل مترجمك يمكنك طرح استثناء c++:

void myTranslator(unsigned code, EXCEPTION_POINTERS*)
{
    throw std::exception(<appropriate string here>);
}

_set_se_translator(myTranslator);

لاحظ أن الكود سيخبرك بالخطأ.تحتاج أيضًا إلى الترجمة باستخدام خيار /EHa (C/C++ -> Code Generatrion -> تمكين استثناءات C/C++ = نعم مع استثناءات SEH).

إذا لم يكن ذلك منطقيًا، فاطلع على المستندات الخاصة بـ [_set_se_translator](http://msdn.microsoft.com/en-us/library/5z4bw5h5(VS.80).aspx)

إذا كان التقاط جميع الاستثناءات - بما في ذلك استثناءات نظام التشغيل - هو ما تحتاجه حقًا، فأنت بحاجة إلى إلقاء نظرة على المترجم ونظام التشغيل لديك.على سبيل المثال، في نظام التشغيل Windows، من المحتمل أن يكون لديك الكلمة الأساسية "__try" أو مفتاح التحويل البرمجي لجعل "try/catch" يلتقط استثناءات SEH، أو كليهما.

اجعل جميع فئات الاستثناءات المخصصة ترث من std::exception، ثم يمكنك ببساطة التقاط std::exception.فيما يلي بعض الأمثلة على التعليمات البرمجية:

class WidgetError
    : public std::exception
{
public:
    WidgetError()
    { }

    virtual ~WidgetError() throw()
    { }

    virtual const char *what() const throw()
    {
        return "You got you a widget error!";
    }
};

في C++، لا يحدد المعيار استثناء القسمة على صفر، وتميل عمليات التنفيذ إلى عدم طرحها.

يمكنك، بالطبع، استخدام catch (...) { /* code here */ }, ولكن الأمر يعتمد حقًا على ما تريد القيام به.في لغة C++، لديك أدوات تدمير حتمية (لا يوجد شيء من هراء الإنهاء)، لذلك إذا كنت تريد التخلص، فإن الشيء الصحيح الذي يجب عليك فعله هو استخدام RAII.

على سبيل المثال.بدلاً من:

void myfunc()
{
    void* h = get_handle_that_must_be_released();
    try { random_func(h); }
    catch (...) { release_object(h); throw; }
    release_object(h);

}

افعل شيئًا مثل:

#include<boost/shared_ptr.hpp>

void my_func()
{
    boost::shared_ptr<void> h(get_handle_that_must_be_released(), release_object);
    random_func(h.get());
}

قم بإنشاء فصلك الدراسي الخاص باستخدام أداة التدمير إذا كنت لا تستخدم التعزيز.

إذا كنت أتذكر بشكل صحيح (لقد مر وقت طويل منذ أن نظرت إلى C++)، أعتقد أن ما يلي يجب أن يفي بالغرض

try
{
 // some code
}
catch(...)
{
 // catch anything
}

وجوجل سريع(http://www.oreillynet.com/pub/a/network/2003/05/05/cpluspocketref.html) يبدو أن يثبت لي الحق.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top