سؤال

هل هناك طريقة لمعرفة وإخراج حجم المكدس الذي تحتاجه الوظيفة في وقت الترجمة في لغة C؟وهنا ما أود أن أعرف:

لنأخذ بعض الوظائف:

void foo(int a) {
    char c[5];
    char * s;
    //do something
    return;
}

عند تجميع هذه الوظيفة، أود أن أعرف مقدار مساحة المكدس التي ستستهلكها عند استدعائها.قد يكون هذا مفيدًا لاكتشاف الإعلان الموجود على المكدس للبنية التي تخفي مخزنًا مؤقتًا كبيرًا.

أنا أبحث عن شيء من شأنه أن يطبع شيئًا مثل هذا:

ملف foo.c :وظيفة استخدام مكدس fo هي n بايت

هل هناك طريقة لعدم النظر إلى التجميع الذي تم إنشاؤه لمعرفة ذلك؟أو الحد الذي يمكن تعيينه للمترجم؟

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

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

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

المحلول

يعمل كود Linux kernel على حزمة 4K على نظام التشغيل x86.ومن ثم يهتمون.ما يستخدمونه للتحقق من ذلك هو نص Perl الذي كتبوه، والذي قد تجده على شكل scripts/checkstack.pl في kernel tarball الأخير (2.6.25 حصل عليه).يتم تشغيله على مخرجات objdump، ووثائق الاستخدام موجودة في التعليق الأولي.

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

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

راجع للشغل، مع objdump من مشروع mingw وActivePerl، أو مع Cygwin، يجب أن تكون قادرًا على القيام بذلك أيضًا على Windows وأيضًا على الثنائيات التي تم الحصول عليها من مترجمين آخرين.

نصائح أخرى

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

شيء مشابه لما هو موجود لـ ADA سيكون جيدًا.انظر إلى صفحة الدليل هذه من دليل البعوضة :

22.2 تحليل استخدام المكدس الثابت

ستقوم الوحدة المترجمة باستخدام -fstack-usage بإنشاء ملف إضافي يحدد الحد الأقصى لمقدار المكدس المستخدم، على أساس كل وظيفة.يحتوي الملف على نفس الاسم الأساسي لملف الكائن الهدف بامتداد .su.يتكون كل سطر من هذا الملف من ثلاثة حقول:

* The name of the function.
* A number of bytes.
* One or more qualifiers: static, dynamic, bounded. 

يتوافق الحقل الثاني مع حجم الجزء المعروف من إطار الوظيفة.

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

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

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

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

بالتأكيد، لا يمكن ضمان أن تكون الإجابة دقيقة بنسبة 100%، نظرًا لأن المترجم يمكنه إجراء أنواع مختلفة من التحسينات مثل الحشو أو وضع المتغيرات في السجلات أو إزالة المتغيرات غير الضرورية تمامًا.لكن أي إجابة تقدمها يجب أن تكون تقديرًا جيدًا على الأقل.

لقد قمت ببحث سريع في جوجل ووجدت StackAnalyzer لكن أعتقد أن أدوات تحليل التعليمات البرمجية الثابتة الأخرى تتمتع بقدرات مماثلة.

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

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

بافتراض أنك تستخدم نظامًا أساسيًا مضمنًا، فقد تجد أن سلسلة الأدوات الخاصة بك لديها القدرة على القيام بذلك.غالبًا ما تنتج المترجمات التجارية الجيدة المضمنة (مثل المترجم Arm/Keil على سبيل المثال) تقارير عن استخدام المكدس.

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

ليس بالضبط "وقت الترجمة"، ولكني سأفعل ذلك كخطوة ما بعد الإنشاء:

  • اسمح للرابط بإنشاء ملف خريطة لك
  • لكل وظيفة في ملف الخريطة، اقرأ الجزء المقابل من الملف القابل للتنفيذ، وقم بتحليل مقدمة الوظيفة.

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

لتنفيذ هذا تحتاج إلى:

  • تكون قادرة على تحليل ملف الخريطة
  • فهم تنسيق الملف القابل للتنفيذ
  • تعرف على الشكل الذي يمكن أن تبدو عليه مقدمة الوظيفة وتكون قادرًا على "فك تشفيرها".

يعتمد مدى سهولة أو صعوبة ذلك على النظام الأساسي المستهدف الخاص بك.(مغروس؟ما هي بنية وحدة المعالجة المركزية؟أي مترجم؟)

من المؤكد أن كل هذا يمكن القيام به في x86/Win32، ولكن إذا لم تفعل شيئًا كهذا مطلقًا وكان عليك إنشاء كل هذا من البداية، فقد يستغرق الأمر بضعة أيام قبل أن تنتهي وتحصل على شيء يعمل.

ليس بشكل عام.تشير مشكلة التوقف في علوم الكمبيوتر النظرية إلى أنه لا يمكنك حتى التنبؤ بما إذا كان برنامج عام سيتوقف عند مدخلات معينة.سيكون حساب المكدس المستخدم لتشغيل البرنامج بشكل عام أكثر تعقيدًا.لذا:لا.ربما في حالات خاصة.

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

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