كيف يمكنني معرفة الاستثناءات التي قد تطرحها دالة دلفي؟

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

  •  09-06-2019
  •  | 
  •  

سؤال

هل هناك طريقة جيدة لمعرفة الاستثناءات التي يمكن أن يثيرها الإجراء/الوظيفة في دلفي (بما في ذلك ما يطلق عليه الإجراءات/الوظائف)؟

في Java، عليك دائمًا أن تعلن عن الاستثناءات التي يمكن طرحها، ولكن هذا ليس هو الحال في دلفي، مما قد يؤدي إلى استثناءات لم تتم معالجتها.

هل توجد أي أدوات لتحليل التعليمات البرمجية تكتشف الاستثناءات غير المعالجة؟

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

المحلول

(يحرر:ومن الواضح الآن أن السؤال المشار إليه فقط لفحص وقت التصميم.)

إجابة جديدة:

لا أستطيع أن أذكر ما إذا كانت هناك أي أدوات للتحقق من ذلك لك.محلل باسكال، على سبيل المثال، لا يفعل ذلك.

أنا يستطيع ومع ذلك، أخبرك أنه في معظم تطبيقات دلفي، حتى لو كانت هناك أداة للتحقق من ذلك، فلن تحصل على أي نتائج.

لماذا؟ لأن حلقة الرسالة الرئيسية في TApplication.Run() تلتف كافة استدعاءات HandleMessage() في كتلة معالجة الاستثناءات، والتي تلتقط كافة أنواع الاستثناءات.وبالتالي سيكون لديك استثناء ضمني/افتراضي يعالج حوالي 99.999% من التعليمات البرمجية في معظم التطبيقات.وفي معظم التطبيقات، ستكون معالجة الاستثناء هذه حوالي 100% من التعليمات البرمجية الخاصة بك - وستكون نسبة 0.001% من التعليمات البرمجية التي لم يتم تضمينها في معالجة الاستثناءات هي التعليمات البرمجية التي يتم إنشاؤها تلقائيًا.

إذا كانت هناك أداة متاحة للتحقق من ذلك، فستحتاج إلى إعادة كتابة Application.run() بحيث لا يتضمن معالجة الاستثناءات.

(الإجابة السابقة:يمكن تعيين معالج الأحداث Application.OnException لالتقاط كافة الاستثناءات التي لا تتم معالجتها بواسطة معالجات الاستثناءات الأخرى.على الرغم من أن هذا هو وقت التشغيل، وبالتالي ربما ليس بالضبط ما تبحث عنه (يبدو أنك تريد التعرف عليهم في وقت التصميم)، إلا أنه يسمح لك باحتجاز أي استثناء لم تتم معالجته في مكان آخر.بالتزامن مع أدوات مثل عناصر JCLDebug الموجودة في ملف مكتبة كود جيدي, ، يمكنك تسجيل تتبع المكدس لمعرفة مكان وسبب حدوث الاستثناء، مما يسمح بإجراء مزيد من التحقيق وإضافة معالجة استثناءات محددة أو منع حول رمز الذنب...)

نصائح أخرى

أعتقد أنك تحاول جعل دلفي تتصرف مثل جافا، وهذا ليس أسلوبًا جيدًا.أنصحك بعدم القلق كثيرًا بشأن الاستثناءات غير المعالجة.في أسوأ الحالات، ستنتقل إلى معالج استثناء VCL العام وتؤدي إلى ظهور مربع حوار رسائل Windows.في التطبيق العادي، لن يقوموا بإيقاف التطبيق.

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

باستثناء فحص الكلمة الأساسية "رفع"، لا يوجد بناء لغة في دلفي يخبر القارئ العادي بالاستثناءات التي يمكن توقعها من إحدى الطرق.

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

ستؤدي إضافة كتلة معالجة الاستثناء إلى إحدى الطرق إلى إضافة بعض تعليمات التجميع إليها (حتى عندما لا يتم تشغيل الاستثناء)، مما يشكل تباطؤًا قابلاً للقياس عند استدعاء الطريقة كثيرًا.

توجد بعض المكتبات التي يمكنها مساعدتك في تحليل استثناءات وقت التشغيل، مثل madExcept, JclDebug, ، و سجل يوريكا.يمكن لهذه الأدوات تسجيل جميع أنواع التفاصيل حول الاستثناء، ويُنصح بشدة باستخدام واحدة منها!

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

أحد الأشياء الأساسية في دلفي هو أن الاستثناءات هرمية:جميع استثناءات اللغة المحددة تنحدر من استثناء, ، على الرغم من أنه من الجدير بالذكر أنه من الممكن بالفعل رفع أي منها كائن تنازلي.

أذا أردت يمسك كل استثناء يتم طرحه في إجراء معين، ما عليك سوى لفه في ملف حاول / باستثناء كتلة، ولكن كما ذكر هذا غير مستحسن.

// Other code . . . 
try
  SomeProcedure()
except  // BAD IDEA!
  ShowMessage('I caught them all!');
end;

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

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

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

أي استثناء لم تتم معالجته بشكل صريح أو عام على مستوى معين سوف يتدفق لأعلى في مكدس الاستدعاءات.ستقوم دلفي RTL (مكتبة وقت التشغيل) بإنشاء مجموعة من فئات الاستثناءات المختلفة - (الأخطاء الرياضية، أخطاء الوصول، الأخطاء الخاصة بالفئات، إلخ).يمكنك اختيار التعامل معها على وجه التحديد أو بشكل عام في المحاولة المختلفة باستثناء الكتل.

لا تحتاج حقًا إلى الإعلان عن أي فئات استثناءات جديدة إلا إذا كنت بحاجة إلى نشر سياق وظيفي محدد مع الاستثناء.

كما كتب المعلقون السابقون، يمكنك أيضًا إضافة أم لجميع معالجات الاستثناءات مثل MadExcept أو EurekaLog للقبض على ما لم يتم اكتشافه.

يحرر:وهذا تأمين شامل ضد الاستثناءات غير المعالجة

try
  ThisFunctionMayFail;
except
  // but it sure won't crash the application
  on e:exception
  do begin
    // something sensible to handle the error 
    // or perhaps log and/or display the the generic e.description message
  end
end;

لوقت التشغيل حاول يوريكالوج.لا أعرف ما إذا كانت هناك أداة لوقت التصميم.سيكون لديك المزيد من الصعوبات حتى عندما يكون لديك كود طرف ثالث بدون مصدر.ليست هناك حاجة في دلفي لالتقاط الاستثناءات، لذلك لا يتعين عليك الإعلان عنها كما هو الحال في Java.

ما أردت قوله هو أن دلفي لا تتطلب معالجة الاستثناء.سوف ينهي البرنامج فقط.يوفر EurekaLog وسيلة لتسجيل الاستثناءات التي تمت معالجتها وغير المعالجة وتوفير قدر كبير من المعلومات حول حالة البرنامج عند حدوث الاستثناء، بما في ذلك سطر التعليمات البرمجية الذي حدث فيه ومكدس الاستدعاءات في ذلك الوقت.

وكما يشير جيم ماكيث، لا يمكنك الحصول على إجابة محددة، ولكن يبدو لي أنه يمكن للمرء أن جزئيا أجب عن السؤال ببعض التحليلات الثابتة:بالنظر إلى وظيفة/إجراء معين، قم بإنشاء رسم بياني للاتصال.تحقق من كل وظيفة في الرسم البياني للاتصال هذا للحصول على بيان الزيادة.سيخبرك ذلك، على سبيل المثال، أن TIdTcpClient.ReadString يمكنه رفع EIdNotConnected (من بين أشياء أخرى).

قد يلاحظ المحلل الذكي أيضًا أن بعض التعليمات البرمجية تستخدم عامل التشغيل / وتتضمن EDivByZero كاحتمال، أو أن بعض الإجراءات تصل إلى مصفوفة وتتضمن ERangeError.

هذه الإجابة أضيق قليلاً من مجرد البحث عن "الزيادة".

يمكن أن تثير أقسام الإنهاء من الوحدات استثناءات أيضًا.هذه سوف تنزلق على ما أعتقد ...وهي أيضًا مشكلة إلى حد ما.

أعتقد أن Delphi IDE يحتوي على "تتبع المكدس" أو "شجرة المكدس" شيء من هذا القبيل.

هذا السؤال يذكرني بلعبة Skybuck's TrusianRoulette...جوجل عليه، قد يساعد الرمز والإجابة.

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