مرجع
آخر الزيارات

تنفيذ رمزي

973 كلمة•0 مشاهدة•🗒️ منذ يوم
باختصار: في علم الحاسوب، يعد التنفيذ الرمزي أو التقييم الرمزي وسيلة لتحليل برنامج لتحديد المدخلات التي تتسبب في تنفيذ كل جزء من البرنامج. تجد هنا «تفاعلات البيئة»، «مثال» و«}» ضمن 13 قسماً.
المحتويات
  1. تفاعلات البيئة
  2. مثال
  3. }
  4. إصدارات سابقة من الأدوات
  5. }
  6. FILE *fp = fopen("doc.txt");
  7. تاريخ
  8. انفجار المسار
  9. data = fgets(..., fp);
  10. تعرج الذاكرة
  11. Symbolic Execution for finding bugs
  12. الكفاءة المعتمدة على البرنامج
  13. مصفوفات

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

علاوةً على ذلك، يطبق مجال المحاكاة الرمزية نفس المفهوم على الأجهزة. يطبق الحساب الرمزي المفهوم على تحليل التعبيرات الرياضية.

تفاعلات البيئة

{

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

مثال

  • ...
  • y = read;
  • z = y * 2;
  • if (z == 12) {
  • fail;
  • } else {
  • printf("OK");
  • }

من جانب آخر، خذ بعين الاعتبار البرنامج أدناه، الذي يقرأ في قيمة ويفشل إذا كان الإدخال 6.int f {

}

...

إصدارات سابقة من الأدوات

وفي هذا السياق، إي إكس إي (EXE) هو إصدار سابق من KLEE. يمكن العثور على ورقة إي إكس إي هنا.

}

من جانب آخر، أثناء التنفيذ العادي (التنفيذ «الملموس»)، سيقرأ البرنامج قيمة إدخال ملموسة (مثلًا، 5) ويعينها إلى y. سيتابع التنفيذ لاحقًا عملية الضرب والفرع الشرطي، والذي سيتم تقييمه إلى خطأ ويطبعOK.

من جهة ثانية، في هذا المثال، قيد المسار هو λ * 2 == 12 للفرع then وλ * 2 != 12 للفرع else. يمكن تنفيذ كلا المسارين بشكل رمزي بشكل مستقل. عندما تنتهي المسارات (مثلًا، نتيجة لتنفيذ fail أو الخروج ببساطة)، يحسب التنفيذ الرمزي قيمة محددة لـ λ عن طريق حل قيود المسار المتراكمة على كل مسار. يمكن اعتبار هذه القيم الملموسة بمثابة حالات اختبار ملموسة يمكن، مثلًا، مساعدة المطورين على إعادة إنتاج الأخطاء. في هذا المثال، سيحدد خلال القيد أنه من أجل الوصول إلى عبارة fail، يجب أن λ تساوي 6.

محددات

ومن ناحية أخرى، أثناء التنفيذ الرمزي، يقرأ البرنامج قيمة رمزية (مثلًا، λ) ويعينها إلى y. ثم يواصل البرنامج عملية الضرب ويخصص λ * 2 إلى z. عند الوصول إلى جملة if، سيتم تقييم λ * 2 == 12. في هذه المرحلة من البرنامج، يمكن أن تأخذ λ أي قيمة، وبالتالي يمكن أن يستمر التنفيذ الرمزي على طول كلا الفرعين، عن طريق «توجيه» مسارين. يحصل كل مسار على نسخة من حالة البرنامج في تعليمات الفرع إلى جانب قيد المسار.

FILE *fp = fopen("doc.txt");

  • ...
  • if (condition) {
  • fputs("some data", fp);
  • } else {
  • fputs("some other data", fp);

تاريخ

  • انظر كذلك
  • حساب رمزي
  • مراجع
  • روابط خارجية

وفي هذا الصدد، تم تقديم مفهوم التنفيذ الرمزي أكاديميًا مع وصف: نظام Select، ونظام EFFIGY، ونظام DISSECT، ونظام Clarke. انظر فهرس يضم المزيد من الأوراق الفنية المنشورة حول التنفيذ الرمزي.

انفجار المسار

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

data = fgets(..., fp);

كذلك، }يفتح هذا البرنامج ملفًا، وبناءً على بعض الشروط، يكتب نوعًا مختلفًا من البيانات إلى الملف. ثم يقرأ البيانات المكتوبة لاحقًا. من الناحية النظرية، سوف ينفذ التنفيذ الرمزي مسارين عند السطر 5 وسيكون لكل مسار من هناك نسخة خاصة به من الملف. وبالتالي، فإن العبارة الموجودة في السطر 11 ستعيد البيانات التي تتوافق مع قيمة «الشرط» في السطر 5. من الناحية العملية، يتم تنفيذ عمليات الملف كمكالمات النظام في النواة، وهي خارجة عن سيطرة أداة التنفيذ الرمزية. الطرق الرئيسية لمواجهة هذا التحدي هي:

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

وفي هذا السياق، تنفيذ المكالمات إلى البيئة مباشرة. ميزة هذا النهج هو أنه سهل التطبيق. العيب هو أن الآثار الجانبية لمثل هذه المكالمات سوف تفسد جميع الحالات التي يديرها محرك التنفيذ الرمزي. في المثال أعلاه، ستعرض التعليمات الموجودة في السطر 11 «بعض البيانات الأخرى للبيانات» اعتمادًا على الترتيب التسلسلي للحالات.

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

تعرج الذاكرة

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

Symbolic Execution for finding bugs

من جهة ثانية، Symbolic Execution and Software Testing presentation at NASA Ames

وفي هذا السياق، Symbolic Execution for Software Testing in Practice – Preliminary Assessment

الكفاءة المعتمدة على البرنامج

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

مصفوفات

وفي السياق ذاته، نظرًا لأن المصفوفة عبارة عن مجموعة من الكثير من القيم المميزة، يجب على المنفذين الرمزية إما التعامل مع المصفوفة بأكملها كقيمة واحدة أو معاملة كل عنصر من عناصر المصفوفة كموقع منفصل. المشكلة في معالجة كل عنصر من عناصر المصفوفة بشكل منفصل هي أنه يمكن تحديد مرجع مثل "[A [i" ديناميكيًا فقط، عندما تكون قيمة i ذات قيمة محددة.

ما رأيك في هذه المقالة؟

📝 هل في هذه المقالة خطأ؟

إذا وجدت معلومة تحتاج تصحيحاً أو إضافة، أو أردت حذف المقالة، أرسل لنا طلباً وسنراجعه.