تمرين - مراقبة المتغيرات وتدفق التنفيذ
توفر طريقة العرض RUN AND DEBUG للمطورين طريقة سهلة لمراقبة المتغيرات والتعبيرات ومراقبة تدفق التنفيذ وإدارة نقاط التوقف أثناء عملية التصحيح.
فحص أقسام طريقة العرض تشغيل وتصحيح الأخطاء
يوفر كل قسم من طريقة عرض RUN AND DEBUG قدرات فريدة. غالبا ما يكون استخدام مجموعة من هذه الأقسام أثناء عملية التصحيح مفيدا.
قسم المتغيرات
مراقبة حالة المتغير هو جانب مهم من تصحيح أخطاء التعليمات البرمجية. غالبا ما تساعد التغييرات غير المتوقعة في حالة المتغير على تحديد الأخطاء المنطقية في التعليمات البرمجية الخاصة بك.
ينظم قسم VARIABLES المتغيرات الخاصة بك حسب النطاق.
Locals يعرض النطاق المتغيرات في النطاق الحالي (الأسلوب الحالي).
إشعار
يعتبر قسم عبارات المستوى الأعلى لتطبيق وحدة التحكم أسلوبه الخاص. أسلوب يسمى Main.
يمكنك فتح (توسيع) النطاقات المعروضة عن طريق تحديد السهم إلى يسار اسم النطاق. يمكنك أيضا فتح المتغيرات والكائنات. تظهر لقطة الشاشة التالية الصفيف الذي numbers تم فتحه ضمن Locals النطاق.
من الممكن أيضا تغيير قيمة متغير في وقت التشغيل باستخدام قسم VARIABLES. يمكنك النقر نقرا مزدوجا فوق اسم المتغير ثم إدخال قيمة جديدة.
قسم WATCH
ماذا لو كنت تريد تعقب حالة متغيرة عبر الوقت أو أساليب مختلفة؟ قد يكون من الممل البحث عن المتغير في كل مرة. هذا هو المكان الذي يأتي قسم WATCH في متناول اليدين.
يمكنك تحديد الزر إضافة تعبير (يظهر كعلامة الجمع: +) لإدخال اسم متغير أو تعبير لمشاهدته. كبديل، يمكنك النقر بزر الماوس الأيمن فوق متغير في قسم VARIABLES وتحديد Add to watch.
سيتم تحديث جميع التعبيرات داخل قسم WATCH تلقائيا أثناء تشغيل التعليمات البرمجية الخاصة بك.
مقطع مكدس الاستدعاءات
في كل مرة تدخل فيها التعليمات البرمجية أسلوبا من أسلوب آخر، تتم إضافة طبقة استدعاء إلى مكدس استدعاء التطبيق. عندما يصبح التطبيق الخاص بك معقدا ولديك قائمة طويلة من الأساليب التي يتم استدعاؤها بواسطة أساليب أخرى، يمثل مكدس الاستدعاءات مسار استدعاءات الأسلوب.
يكون قسم CALL STACK مفيدا عندما تحاول العثور على الموقع المصدر لاستثناء أو تعبير WATCH. إذا طرح تطبيقك استثناء غير متوقع، فسترى غالبا رسالة في وحدة التحكم تشبه ما يلي:
Exception has occurred: CLR/System.DivideByZeroException
An unhandled exception of type 'System.DivideByZeroException' occurred in Debug1.dll: 'Attempted to divide by zero.'
at Program.<<Main>$>g__WriteMessage|0_1() in C:\Users\howdc\Desktop\Debug1\Program.cs:line 27
at Program.<<Main>$>g__Process1|0_0() in C:\Users\howdc\Desktop\Debug1\Program.cs:line 16
at Program.<Main>$(String[] args) in C:\Users\howdc\Desktop\Debug1\Program.cs:line 10
تسمى مجموعة at Program ... الأسطر ذات المسافة البادئة ضمن رسالة الخطأ تتبع المكدس. يسرد تتبع المكدس اسم وأصل كل أسلوب تم استدعاؤه مما يؤدي إلى الاستثناء. على الرغم من ذلك، قد يكون من الصعب قليلا فك المعلومات، لأنها يمكن أن تتضمن أيضا معلومات من وقت تشغيل .NET. في هذا المثال، تتبع المكدس نظيف جدا ويمكنك أن ترى أن الاستثناء حدث في أسلوب يسمى WriteMessage. ينشأ المكدس في أسلوب يسمى Main، وهو قسم عبارات المستوى الأعلى من تطبيق وحدة التحكم.
يمكن أن يساعدك قسم CALL STACK على تجنب صعوبة فك تتبع المكدس المشوش بمعلومات وقت تشغيل .NET. يقوم بتصفية المعلومات غير المرغوب فيها لإظهار الأساليب ذات الصلة فقط من التعليمات البرمجية الخاصة بك بشكل افتراضي. يمكنك إلغاء مكدس الاستدعاءات يدويا لمعرفة مكان إنشاء الاستثناء.
مقطع BREAKPOINTS
يعرض قسم BREAKPOINTS إعدادات نقطة التوقف الحالية ويمكن استخدامه لتمكين نقاط توقف معينة أو تعطيلها أثناء جلسة تصحيح الأخطاء.
تكوين التطبيق الخاص بك وتشغيل التكوين
عند العمل على تطبيق وحدة تحكم يقرأ إدخال المستخدم، ستحتاج على الأرجح إلى تحديث ملف تكوين التشغيل.
تحديث التعليمات البرمجية في ملف Program.cs كما يلي:
string? readResult; int startIndex = 0; bool goodEntry = false; int[] numbers = { 1, 2, 3, 4, 5 }; // Display the array to the console. Console.Clear(); Console.Write("\n\rThe 'numbers' array contains: { "); foreach (int number in numbers) { Console.Write($"{number} "); } // To calculate a sum of array elements, // prompt the user for the starting element number. Console.WriteLine($"}}\n\r\n\rTo sum values 'n' through 5, enter a value for 'n':"); while (goodEntry == false) { readResult = Console.ReadLine(); goodEntry = int.TryParse(readResult, out startIndex); if (startIndex > 5) { goodEntry = false; Console.WriteLine("\n\rEnter an integer value between 1 and 5"); } } // Display the sum and then pause. Console.WriteLine($"\n\rThe sum of numbers {startIndex} through {numbers.Length} is: {SumValues(numbers, startIndex)}"); Console.WriteLine("press Enter to exit"); readResult = Console.ReadLine(); // This method returns the sum of elements n through 5 static int SumValues(int[] numbers, int n) { int sum = 0; for (int i = n; i < numbers.Length; i++) { sum += numbers[i]; } return sum; }خذ دقيقة لمراجعة التعليمات البرمجية.
لاحظ ما يلي:
- تحدد التعليمات البرمجية صفيف عدد صحيح يحتوي على خمسة أرقام.
- تعرض التعليمات البرمجية الإخراج في وحدة التحكم.
- تطالب التعليمات البرمجية المستخدم بإدخال رقم
nعنصر بدء يستخدمه لجمع عناصرnالصفيف من خلال5. - تحسب التعليمات البرمجية المجموع في أسلوب، وتعرض النتائج في وحدة التحكم، ثم تتوقف مؤقتا.
إشعار
لا تدعم لوحة وحدة تحكم DEBUG إدخال المستخدم من وحدة التحكم.
في قائمة ملف Visual Studio Code، حدد Save.
في قائمة Run ، حدد Remove All Breakpoints.
يؤدي ذلك إلى إزالة أي نقاط توقف متبقية من التمرين السابق.
في طريقة العرض RUN AND DEBUG، حدد Start Debugging.
لاحظ حدوث خطأ عند
Console.Clear();تنفيذ سطر التعليمات البرمجية.في شريط أدوات تتبع الأخطاء، حدد إيقاف.
قم بالتبديل إلى طريقة عرض EXPLORER، ثم افتح ملف launch.json في المحرر.
تحديث قيمة السمة
consoleكما يلي:"console":"integratedTerminal",في القائمة Visual Studio Code File ، حدد Save، ثم أغلق ملف launch.json.
مراجعة إخراج التطبيق وتحديد المشكلات
يمكن أن تكشف مراجعة إخراج التطبيق الخاص بك عن مشكلات المنطق التي تجاهلتها عند كتابة التعليمات البرمجية الخاصة بك.
قم بالتبديل مرة أخرى إلى طريقة عرض RUN AND DEBUG.
في طريقة العرض RUN AND DEBUG، حدد Start Debugging.
تظهر الرسائل المعروضة على لوحة وحدة تحكم DEBUG مصحح الأخطاء المرفق بالتطبيق
Debug101.dll.لاحظ أنه لا يتم عرض رسائل خطأ.
تغيير قيمة السمة
consoleمن internalConsole إلى integratedTerminal في ملف تكوين التشغيل قد أصلح خطأ وحدة التحكم. ولكن الآن تحتاج إلى تحديد موقع وحدة التحكم التي تحتوي على الإخراج الخاص بك.في منطقة اللوحات أسفل المحرر، قم بالتبديل من لوحة وحدة تحكم DEBUG إلى لوحة TERMINAL.
لاحظ أن تنفيذ التعليمات البرمجية قد توقف مؤقتا عند الرسالة التي تطالب المستخدم بإدخال قيمة ل
n.يجب أن يبدو الإخراج على لوحة TERMINAL كما يلي:
The 'numbers' array contains: { 1 2 3 4 5 } To sum values 'n' through 5, enter a value for 'n':في موجه الأوامر TERMINAL، أدخل 3
راجع الإخراج من التطبيق.
يجب أن يبدو الإخراج على لوحة TERMINAL كما يلي:
The 'numbers' array contains: { 1 2 3 4 5 } To sum values 'n' through 5, enter a value for 'n': 3 The sum of numbers 3 through 5 is: 9 press Enter to exitخذ دقيقة للنظر في القيمة المبلغ عنها ل
sumوقيم عناصر الصفيف من 3 إلى 5 المعروضة في أعلى وحدة التحكم.الرسالة تقول:
The sum of numbers 3 through 5 is: 9. ومع ذلك، فإن عناصر الصفيف من 3 إلى 5 هي3و4و.5ألا يجب أن يكون المجموع المبلغ عنه 12؟يمكنك استخدام قسم VARIABLES في طريقة عرض RUN AND DEBUG للتحقيق في المشكلة.
مراقبة حالة المتغير
في بعض الحالات، ببساطة مراقبة حالة المتغير كافية لتحديد مشكلة المنطق في التطبيق الخاص بك.
تعيين نقطة توقف على سطر التعليمات البرمجية التالي:
Console.WriteLine($"\n\rThe sum of numbers {startIndex} through {numbers.Length} is: {SumValues(numbers, startIndex)}");في طريقة العرض RUN AND DEBUG، حدد Start Debugging.
التبديل من لوحة وحدة تحكم DEBUG إلى لوحة TERMINAL.
في موجه الأوامر TERMINAL، أدخل 3
سيتم إيقاف تنفيذ التعليمات البرمجية مؤقتا عند نقطة التوقف.
خذ دقيقة لمراجعة قسم VARIABLES في طريقة عرض RUN AND DEBUG.
لاحظ أنه
startIndexتم تعيين القيمة التي أدخلتها، وهي3.حدد خطوة إلى.
لاحظ أنه يتم تحديث مقاطع VARIABLES و CALL STACK.
يوضح قسم CALL STACK أن تنفيذ التعليمات البرمجية
SumValuesقد انتقل إلى الأسلوب .يعرض قسم VARIABLES، الذي يسرد المتغيرات المحلية، قيمة العدد الصحيح
n. يتم تعيين قيمة معلمةnالأسلوب من وسيطةstartIndexاستدعاء الأسلوب . في هذه الحالة، يجعل التغيير إلى أسماء المتغيرات من الواضح أن القيمة قد تم تمريرها، وليس مؤشرا مرجعيا.إشعار
في هذه الحالة، يمكنك مشاهدة معظم التعليمات البرمجية الخاصة بك في المحرر، لذلك قد لا تحتاج إلى قسم CALL STACK، ولكن عندما تعمل على تطبيقات أكبر مع استدعاءات أسلوب متداخلة ومترابطة للغاية، يمكن أن يكون مسار التنفيذ الموضح في قسم CALL STACK مفيدا للغاية.
تابع تحديد Step Into حتى لا تعود
sumالقيمة المعينة إلى0.خذ دقيقة لمراجعة المعلومات الموضحة في قسم VARIABLES.
يجب أن ترى ما يلي:
لاحظ أن القيمة المعينة ل
sumانتقلت من0إلى4.لتوسيع
numbersالصفيف، حدد الأرقام [int[]].
تذكر أنه يتم الوصول إلى عناصر الصفيف باستخدام أرقام الفهرس المستندة إلى الصفر.
في هذه الحالة، يكون خطأ المنطق هو تعارض بين الإرشادات الموجودة في واجهة المستخدم والتعليمات البرمجية الأساسية. تشير واجهة المستخدم إلى عناصر الصفيف 1-5. ومع ذلك، تستخدم التعليمات البرمجية القيمة التي أدخلها المستخدم للوصول إلى عناصر الصفيف المستندة إلى الصفر. يخزن عنصر الصفيف الذي يحتوي على فهرس
3قيمة .4لا تعوض التعليمات البرمجية عن أرقام الفهرس المستندة إلى الصفر.لإنهاء جلسة تصحيح الأخطاء، حدد إيقاف.
خذ دقيقة للنظر في كيفية إصلاح المشكلة.
يمكن تصحيح هذه المشكلة في واجهة المستخدم عن طريق مطالبة المستخدم بإدخال قيمة بين 0 و4. يمكن أيضا تصحيحه في التعليمات البرمجية عن طريق طرح 1 من القيمة التي تم إدخالها. بشكل عام، يجب أن يكون هدفك واضحا وسهلا لاتباع واجهة المستخدم. في هذه الحالة قد يكون من الأفضل تحديث التعليمات البرمجية كما يلي:
Console.WriteLine($"\n\rThe sum of numbers {startIndex} through {numbers.Length} is: {SumValues(numbers, startIndex - 1)}");سيؤدي تشغيل التعليمات البرمجية المحدثة إلى إنتاج الإخراج التالي:
قم بتحديث التعليمات البرمجية باستخدام الأسلوب المقترح، ثم احفظ ملف Program.cs.
قم بإلغاء تحديد نقطة التوقف، وأعد تشغيل التطبيق في مصحح الأخطاء، وتحقق من عرض النتيجة المقصودة في TERMINAL.
لقد استخدمت للتو حالة متغيرة لتحديد مشكلة منطقية وإصلاحها! عمل رائع.
مراقبة تعبيرات المراقبة
يمكن استخدام قسم WATCH لمراقبة التعبيرات التي تستند إلى متغير واحد أو أكثر.
لنفترض أنك تعمل على تطبيق يقوم بإجراء حسابات رقمية على مجموعة بيانات. تعتقد أن التعليمات البرمجية الخاصة بك تنتج نتائج غير موثوق بها عندما تكون النسبة بين متغيرين رقميين أكبر من 5. يمكنك استخدام قسم WATCH لمراقبة النسبة المحسوبة.
تحديث ملف Program.cs بالتعليمات البرمجية التالية:
bool exit = false; var rand = new Random(); int num1 = 5; int num2 = 5; do { num1 = rand.Next(1, 11); num2 = num1 + rand.Next(1, 51); } while (exit == false);احفظ ملف Program.cs.
تعيين نقطة توقف على سطر التعليمات البرمجية النهائي.
تعيين تعبير WATCH التالي:
num2 / num1 > 5في طريقة العرض RUN AND DEBUG، حدد Start Debugging.
لاحظ القيم المعروضة في قسمي VARIABLES و WATCH.
حدد متابعة حتى ترى تعبير WATCH يقيم إلى
true.إذا تم تقييم تعبير WATCH إلى
trueفي التكرار الأول، فحدد متابعة عدة مرات أخرى أو حتى ترىtrueمرة ثانية.خذ دقيقة للنظر في كيفية استخدام قسم WATCH.
في هذا السيناريو، حددت أن التعليمات البرمجية الخاصة بك تنتج نتائج غير موثوق بها عندما تكون النسبة بين متغيرين رقميين أكبر من 5. لقد أنشأت تعبيرا في قسم WATCH يمثل هذا الشرط. يمكنك الآن استخدام قسم WATCH لتعقب هذا الشرط.
تعديل القيمة المعينة إلى متغير في قسم VARIABLES
قد تكون هناك أوقات تريد فيها إنشاء شرط برمجي يدويا. يمكنك قسم VARIABLES في طريقة عرض RUN AND DEBUG من القيام بذلك عن طريق تغيير حالة متغير في وقت التشغيل.
خذ دقيقة لمراجعة التعليمات البرمجية التي تقوم بتشغيلها.
لاحظ أن التعليمات البرمجية لن تخرج أبدا من الحلقة
doلأنهexitلن يكونtrueأبدا . هذا ليس شرطا برمجيا تحتاج إلى تغييره في تطبيق في العالم الحقيقي، ولكنه يوضح القدرة.في قسم VARIABLES، انقر بزر الماوس الأيمن فوق
exit [bool]، ثم حدد Set Value.يمكنك قسم VARIABLES من تغيير القيمة المعينة إلى متغير في وقت التشغيل. يمكن أن يكون هذا مفيدا عندما تريد معرفة كيفية تفاعل التعليمات البرمجية الخاصة بك مع شرط معين.
لتعيين قيمة
exitإلىtrue، اكتب true ثم اضغط على Enter.في هذه الحالة، سيؤدي تغيير قيمة
exitإلىtrueإلى إغلاق التطبيق عند تنفيذ العبارةwhile.حدد متابعة.
لاحظ أن لوحة وحدة تحكم DEBUG تعرض رسالة تعلمك بإنهاء البرنامج.
تهانينا! لقد استخدمت بنجاح مقاطع VARIABLES و WATCH في طريقة عرض RUN AND DEBUG.
خلاصة
فيما يلي بعض الأشياء المهمة التي يجب تذكرها من هذه الوحدة:
- مراقبة حالة المتغير باستخدام قسم VARIABLES في طريقة عرض RUN AND DEBUG.
- تعقب تعبير عبر الوقت أو أساليب مختلفة باستخدام قسم WATCH في طريقة عرض RUN AND DEBUG.
- استخدم قسم CALL STACK في طريقة العرض RUN AND DEBUG للعثور على الموقع المصدر لاستثناء أو تعبير WATCH.
- استخدم قسم VARIABLES لتغيير القيمة المعينة للمتغير في وقت التشغيل.