بسم الله الرحمن الرحيم
كيف الحال شباب
أعتقد إني فتحت عشرين موضوع مع بعض
ولكن صدقوني كلها تصب في مكان واحد
فهم عمل الكمبيوتر ( وإلى فما معنى مبرمج)
بصراحة : نحن كمبرمجين عرب تعتبر برامجنا ( نكتة عند العالم)
والسبب كثرة الأخطاء ... هل تعرف أي برنامج مبتدأ (ليس عربي بالتحديد)
جرب شغلة -إفتح كل النوافذ الي فية - شغل 20 برنامج في جهازك - نزلة - طلعة
شوف شو بيصير بيظهر مسج ( خطأ غير متوقع - باي ) هذا إذا عرض رسالة
والحل : كيف أصنع برنامج يحل الأخطاء ذاتيا ( ينهار نظام التشغيل ولا ينهار البرنامج ؟؟!)
الموضوع طويل جدا ( ولذلك نقسمة إلى عدة أقسام )
- كتابة كود داخل برنامج ( لتصحيح أي خطأ متوقع أو غير متوقع يتعرض لة البرنامج ومحاولة تصحيحة)
- والقسم الثاني : تصميم برامج الديبغر مثل ( olly - turbo DBG ) و البرامج التي تأتي مع المترجمات
وأكيد لو إفتهم الدرس الأول (سيصبح تصميم برامج التنقيح مجرد تطبيق )
نبدأ الشرح
كتابة برنامج تصحيح ذاتي ( داخل برنامج)
ماذا يمكن أن أستفيد من هذا الموضوع؟ سؤال يطرح نفسة
مثال: شغل مترجم الفجول سي وطبق
#include "stdafx.h"
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
char* pstr=NULL;
strcpy(pstr,"fff");
MessageBox (NULL,"main",NULL,MB_OK);
return 0;
}هذا خطأ واضح وشاهد رسالة الخطأ الرهيبة
ولن ينفذ المسج بل سيطرد برنامجك من الذاكرة
سنقوم الآن بكتابة برنامج تصحيح ذاتي
لكي يتفاهم مع النظام ويحل المشكلة (ولاينطرد بسهولة)
لاحظ الكود
#include "stdafx.h"
void FnError(DWORD);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
__try{
char* pstr=NULL;
strcpy(pstr,"fff");
}
__except (FnError(GetExceptionCode()))
{
}
MessageBox (NULL,"main",NULL,MB_OK);
return 0;
}
void FnError(DWORD ErrCode)
{
MessageBox (NULL,"Error",NULL,MB_OK);
}ما رأيك هل فتحنا فرصة للنقاش ومعرفة الخطأ
طريقة عمل البرنامج
يبدأ تنفيذ بلوك try
وأي خطأ يحدث يقوم البرنامج بتنفيذ محتوى except
وهي الدالة
FnError
هذة الدالة هي التي يجب أن تحل المشكلة
ملاحظة(في مثالنا الخطأ بسيط ويمكن أن يحلة نظام التشغيل )
ويستمر تنفيذ البرنامج
ملاحظة يمرر للدالة FnError معرف الخطأ
وهو العائد من الدالة GetExceptionCode
وفي قانون يقول لحل أي مشكلة نبدأ بمعرفة المشكلة
وسيكون الشرح كلة على الدالة FnError
أول شيء نعرفة ماهو الخطأ أو الإستثاء
نبدأ بسرد كل الأخطا التي في النظام
وهي :
void FnError(DWORD ErrCode)
{
switch (ErrCode)
{
case STATUS_WAIT_0:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_ABANDONED_WAIT_0:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_USER_APC:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_TIMEOUT:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_PENDING:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_SEGMENT_NOTIFICATION:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_GUARD_PAGE_VIOLATION:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_DATATYPE_MISALIGNMENT:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_BREAKPOINT:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_SINGLE_STEP:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_ACCESS_VIOLATION:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_IN_PAGE_ERROR:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_INVALID_HANDLE:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_NO_MEMORY:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_ILLEGAL_INSTRUCTION:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_NONCONTINUABLE_EXCEPTION:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_INVALID_DISPOSITION:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_ARRAY_BOUNDS_EXCEEDED:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_FLOAT_DENORMAL_OPERAND:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_FLOAT_DIVIDE_BY_ZERO:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_FLOAT_INEXACT_RESULT:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_FLOAT_INVALID_OPERATION:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_FLOAT_OVERFLOW:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_FLOAT_STACK_CHECK:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_FLOAT_UNDERFLOW:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_INTEGER_DIVIDE_BY_ZERO:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_INTEGER_OVERFLOW:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_PRIVILEGED_INSTRUCTION:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_STACK_OVERFLOW:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_CONTROL_C_EXIT:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_FLOAT_MULTIPLE_FAULTS:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_FLOAT_MULTIPLE_TRAPS:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_ILLEGAL_VLM_REFERENCE:
MessageBox (NULL,"",NULL,MB_OK);
break;
}
}هذة أعتقد أنها كل الأخطاء التي يمكن أن تحدث
في ملاحظة : كل الأخطاء التي تبدأ ب STATUS_ أو EXCEPTION
فإنها نفس الشيء
مثال :EXCEPTION_ACCESS_VIOLATION = STATUS_ACCESS_VIOLATION
وفي شيء ثاني في دالة المقارنة تركت كل المسجات فاضية لكي تكتب فيها
ما تريد أن يظهر لتمييز الأخطاء - أنا عن نفسي أكتب إسم الخطأ نفسة
إكتب إسماء الأخطاء ونفذ البرنامج
تلاحظ أن الخطأ هو :STATUS_ACCESS_VIOLATION
وهو أكثر خطأ حدوث في البرامج
ومعناة ( موقع القرائة أو الكتابة في الذاكرة غير موجود أو لا يمكن الوصول إلية)
الدالة أو المايكرو لم يجد مكان للكتابة في الذاكرة ولذلك سيظهر خطأ مباشر
يكفي أن نعرف في هذا الدرس ماهو الخطأ
وبالطبع لا أقدر شرح كل خطأ وطرح أمثلة لها
لأن بعضها لم يعد يحدث في النظام وبعضها لة أكثر من طريقة وبعضها لا أعرفها
ولكني أعدك بأن تعرف أغلبها عند الإنتهاء من سلسلة الدروس
والسبب : لأن كل خطأ يجب أن يقال في وقتة
نكمل الشرح :
بعد أن نحدد ماهو الخطأ يجب أن نصححة
ولتصحيحة يجب أن نعرف موقعة في الذاكرة
ونعرف كل قيم مسجلات المعالج
بريحك ( كل هذة المعلومات) تشملهم دالة واحدة
وهي : GetExceptionInformation
ولا تطلب منك إدخال أي بارمتر ولكنها تعيد الكثير
تعيد مؤشرين لسجلين مهمين وهما
PEXCEPTION_RECORD
PCONTEXT
المؤشر الأول عبارة عن مؤشر لمسجل الإستثنائات
ماهو جدول الإستثنائات : PEXCEPTION_RECORD
بإختصار يهمنا أو يكفي أن نعرف من هذا السجل
متغيرين فقط هما ( رقم الخطأ - عنوان الخطأ في البرنامج)
وهما : ExceptionCode - ExceptionAddress
أولا رقم الخطأ أوشفرة الخطأ هو نفسة الذي تحدثنا عنة
والتي تعيدة الدالة GetExceptionCode
أما العنوان فهو الذي يهمنا (وهو عنوان الخطأ)
المؤشر الثاني : PCONTEXT
وهو جدول لمسجلات المعالج -eax,ebx,esp,....
ومسجلات المقاطع - DS,CS,ES....
ومسجلات الحالة (بإختصار وكأن برنامجك داخل منقح برامج)
وأكيد بعد ما نعرف كل شيء عن البرنامج وقت الخطأ
يسهل التصحيح .
ولآن بعد أن عرفنا معنى الأخطأ خلنا نكتب الكود الصحيح
بهذا الشكل يكتب كود تصحيح الأخطا
#include "stdafx.h"
void FnError(LPEXCEPTION_POINTERS);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
__try{
char* pstr=NULL;
strcpy(pstr,"fff");
}
__except (FnError(GetExceptionInformation ()))
{
}
MessageBox (NULL,"main",NULL,MB_OK);
return 0;
}
void FnError(LPEXCEPTION_POINTERS ErrRec)
{
char reg[MAX_PATH];
LPCONTEXT pcontext=ErrRec->ContextRecord;
LPEXCEPTION_RECORD exrec=ErrRec->ExceptionRecord;
////إظهار مسجلات المعالج
wsprintf(reg,"EAX=%X - EBX=%X - ECX=%X - EDX=%X",pcontext->Eax,pcontext->Ebx,pcontext->Ecx,pcontext->Edx);
MessageBox (NULL,reg,NULL,MB_OK);
switch (exrec->ExceptionCode)
{
case STATUS_WAIT_0:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_ABANDONED_WAIT_0:
MessageBox (NULL,"",NULL,MB_OK);
break;
case STATUS_USER_APC:
MessageBox (NULL,"",NULL,MB_OK);
break;
...
...
..كل الإحتمالات
...
...
}}أعتقد لوفهمت هذا الدرس
يكفي اليوم..
في ملاحظة
مسجل PCONTEXT
لايحتوي مسجلات المعالج للبرنامج فقط
وإنما يحتوي مسجلات الهاردوير(نقط توقف للأجهزة)
كما يحتوي على مسجلات الديبغر للنظام
كما يحتوي على مسجلات لمعالجات أخرى
وسيتم شرح كل شيء في وقتة
أهم شيء
مافي برامج عربية بأخطاء
هذا والله أعلم
وبالتوفيق



