English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
معالجة الأخطاء أثناء تشغيل البرنامج أمر ضروري، حيث قد تحدث أخطاء غير متوقعة أثناء إجراء عمليات ملف، نقل البيانات وتشغيل خدمات الويب. إذا لم يتم التعامل مع معلومات الأخطاء بشكل صحيح، قد يؤدي ذلك إلى تسريب المعلومات وعدم قدرة البرنامج على التشغيل.
في أي لغة برمجة، تحتاج إلى معالجة الأخطاء. أنواع الأخطاء تشمل:
الخطأ النحوي
خطأ التشغيل
الخطأ النحوي عادةً يحدث بسبب استخدام مكونات البرنامج بشكل غير صحيح (مثل العمليات، التعبيرات). مثال بسيط كما يلي:
-- ملف test.lua a == 2
نتيجة تنفيذ الكود أعلاه هي:
lua: test.lua:2: خطأ في النحو قرب '=='
كما ترون، حدث خطأ في النحو أعلاه، "=" و "==" مختلفان. "=" هو تعبير تعيين، بينما "==" هو عملية مقارنة.
مثال آخر:
for a=1,10 print(a) end
سيظهر الخطأ التالي عند تنفيذ البرنامج أعلاه:
lua: test2.lua:2: 'do' متوقع قرب 'print'
خطأ النحو أكثر بساطة من خطأ التشغيل، لا يمكن تحديد خطأ التشغيل بشكل دقيق، بينما يمكننا حل خطأ النحو بسرعة، مثل المثال أعلاه، فقط بحاجة إلى إضافة do تحت جملة for:
for a=1,10 do print(a) end
خطأ التشغيل هو أن البرنامج يمكن تنفيذه بشكل طبيعي، لكنه سيقوم بطباعة رسالة خطأ. مثل المثال أدناه، بسبب خطأ في إدخال المعاملات، تم إصدار خطأ عند تشغيل البرنامج:
function add(a,b) يعود a+b end add(10)
عندما نكتب ونشغل الكود التالي، يمكن للترميز أن ينجح، لكن عند التشغيل سيظهر الخطأ التالي:
lua: test2.lua:2: محاولة تنفيذ حساب على local 'b' (قيمة nil) تتبع السلسلة: stack traceback: test2.lua:2: في function 'add' test2.lua:5: في chunk الرئيسي [C]: ?
عند استدعاء الدالة في lua، حتى إذا كانت قائمة المعاملات ليست متطابقة مع قائمة المعاملات، يمكن استدعاء الدالة بنجاح، سيتم التخلص من المعاملات الزائدة، وسيتم تعديل المعاملات المفقودة إلى nil.
المعلومات المقدمة أعلاه حول الأخطاء هي بسبب أن المعامل b تم تعديله إلى nil بعد ذلك، تم دمج nil في عملية الحساب +.
إذاً: add في الدالة: "return a+b" بدلاً من: "print(a,b)" فالنتيجة ستكون: "10 nil" لن يحدث خطأ.
يمكننا استخدام إثنين من الدوال: assert و error لمعالجة الأخطاء. مثال أدناه:
local function add(a,b) assert(type(a) == "number", "a ليسرقما") assert(type(b) == "number", "b ليسرقما") يعود a+b end add(10)
سيظهر الخطأ التالي عند تنفيذ البرنامج أعلاه:
lua: test.lua:3: b ليسرقما تتبع السلسلة: stack traceback: [C]: في function 'assert' test.lua:3: في local 'add' test.lua:6: in main chunk [C]: في ?
مثالًا، يتحقق assert أولاً من أول معامل، إذا لم يكن هناك خطأ، لا يقوم assert بأي شيء؛ وإلا، يرcthrow assert كرسالة خطأ كثاني معامل.
تنسيق الجملة كالتالي
error (message[, level])
الوظيفة: إنهاء تنفيذ الدالة الحالية وعدة محتوى الرسالة كرسالة خطأ (لا يمكن للدالة error العودة أبدًا)
عادةً، يتم إضافة معلومات موقع الخطأ إلى رأس رسالة error
يحدد معامل Level موقع الحصول على الخطأ:
Level=1[الافتراضي]:يحدد موقع دالة error (ملف + رقم السطر)
Level=2: يشير إلى دالة دالة error
Level=0: لا تضيف معلومات موقع الخطأ
معالجة الأخطاء في Lua باستخدام دالة pcall (protected call) لتغليف الكود الذي يجب تنفيذه.
تستقبل pcall دالة واحدة والمعاملات التي يتم تمريرها إلى هذه الدالة، وتنفيذها، نتيجة التنفيذ: هناك خطأ، لا يوجد خطأ؛ عودة true أو false، errorinfo.
تنسيق الجملة كالتالي
if pcall(function_name, ...) then -- لا يوجد أخطاء else -- بعض الأخطاء end
مثال بسيط:
> =pcall(function(i) print(i) end, 33) 33 true > =pcall(function(i) print(i) error('error..') end, 33) 33 false stdin:1: error..
لاحظ هنا الحكم على قيم العودة:
> function f() return false,2 end > if f() then print '1' else print '0' end 0
يستدعي pcall المعامل الأول بـ "وضع الحماية"، لذا يمكن لـ pcall التقاط أي أخطاء تحدث أثناء تنفيذ الدالة.
عادةً عند حدوث خطأ، نرغب في الحصول على معلومات تفصيلية أكثر حول الخطأ وليس فقط موقع حدوثه. لكن عند عودة pcall، يتم تدمير جزء من قائمة الاستدعاء.
Lua يقدم دالة xpcall، تقوم دالة xpcall باستقبال المعامل الثاني - دالة معالجة الأخطاء، وعند حدوث خطأ، يتم استدعاء دالة معالجة الأخطاء قبل توسيع قائمة الاستدعاء (unwind)، لذا يمكن استخدام مكتبة debug هنا للحصول على معلومات إضافية حول الخطأ.
يقدم مكتبة debug دويتين عامتين لمعالجة الأخطاء:
debug.debug: يقدم وحة تحكم Lua للتحقق من أسباب الأخطاء
debug.traceback: بناء رسالة خطأ مدمجة بناءً على السلسلة التشغيلية
>=xpcall(function(i) print(i) error('error..') end, function() print(debug.traceback()) end, 33) 33 تتبع السلسلة: stack traceback: stdin:1: في الوظيفة <stdin:1> [C]: في الوظيفة 'error' stdin:1: في الوظيفة <stdin:1> [C]: في الوظيفة 'xpcall' stdin:1: في الكتلة الرئيسية [C]: في ? false nil
مثال على استخدام xpcall 2:
function myfunction () n = n / nil end function myerrorhandler( err ) print( "ERROR:", err ) end status = xpcall( myfunction, myerrorhandler ) print( status )
سيظهر الخطأ التالي عند تنفيذ البرنامج أعلاه:
خطأ: test2.lua:2: محاولة إجراء حساب على العالمية 'n' (قيمة فارغة) false