سؤال

هل هناك أي قواعد عامة عند استخدام العودية على كيفية تجنب stackoverflows?

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

المحلول

كم مرة سوف تكون قادرة على recurse تعتمد على:

  • كومة الحجم (التي عادة ما تكون 1MB IIRC, ولكن الثنائية يمكن أن تكون اليد تحريرها ؛ لا ننصح بذلك)
  • كم كومة كل مستوى من العودية يستخدم (الأسلوب مع 10 uncaptured Guid المتغيرات المحلية سيتم اتخاذ المزيد من كومة من الأسلوب الذي لا يملك أي المتغيرات المحلية ، على سبيل المثال)
  • JIT كنت تستخدم أحيانا JIT سوف استخدام ذيل العودية, مرة أخرى أنه لن.قواعد معقدة و لا أستطيع تذكر لهم.(هناك بلوق وظيفة من قبل ديفيد Broman العودة من 2007, ، MSDN الصفحة من نفس المؤلف/تاريخ, ولكن قد يكون قديما الآن.)

كيفية تجنب امتدت مكدس?لا recurse كثيرا :) إذا كنت لا يمكن أن يكون متأكد من أن الإعادة سيتم إنهاء دون الذهاب بعيدا جدا (سأكون قلقا في "أكثر من 10" على الرغم من انها آمنة جدا) ثم كتابة ذلك لتجنب التكرار.

نصائح أخرى

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

public int CalculateSomethingRecursively(int someNumber)
{
    return doSomethingRecursively(someNumber, 0);
}

private int doSomethingRecursively(int someNumber, int level)
{
    if (level >= MAX_LEVEL || !shouldKeepCalculating(someNumber))
        return someNumber;
    return doSomethingRecursively(someNumber, level + 1);
}

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

وأنا لست على علم بأي على وضع الصعب لتجنب stackoverflows. أنا شخصيا محاولة لضمان - منتديات 1. لدي حالات قاعدة حقي.
2. كود يصل الحال القاعدة في مرحلة ما.

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

وخصوصا إذا كنت تفعل مستويات متعددة من العودية (A-> B-> C-> A-> B ...) قد تجد أنه يمكنك استخراج واحدة من تلك المستويات في حلقة وتنقذ نفسك بعض الذاكرة.

والحد الطبيعي، إذا ما تركت ليس كثيرا على المكدس بين الاستدعاءات المتتالية، حوالي 15000-25000 مستويات عميقة. 25٪ من ذلك إذا كنت على 6 + IIS.

ويمكن التعبير عن معظم algorhitms متكررة بشكل متكرر.

وهناك طريقة مختلفة لزيادة مساحة مكدس المخصصة، ولكنني سوف بدلا تمكنك من العثور على نسخة تكرارية أولا. :)

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

وأنا مجرد التفكير في ذيل العودية، ولكن اتضح فيما بعد، أن C # لا يعتمد عليه. إلا أن صافي-الإطار يبدو لتقديم الدعم لها:

HTTP: // بلوق .msdn.com / abhinaba / أرشيف / 2007/07/27 / الذيل العودية على اساس net.aspx

وحجم كومة الافتراضي للموضوع هو 1 MB، إذا كنت تعمل تحت CLR الافتراضي. ومع ذلك، قد تتغير المضيفين الآخرين ذلك. على سبيل المثال المضيف ASP يتغير الافتراضي إلى 256 كيلو بايت. وهذا يعني أنه قد تضطر التعليمات البرمجية التي يعمل تماما بشكل جيد في ظل VS، ولكن يكسر عند نشر إلى بيئة استضافة الحقيقية.

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

يمكنك تعديل رأس PE للثنائي نفسها لتغيير الحجم الافتراضي. وهذا مفيد إذا كنت ترغب في تغيير حجم للموضوع الرئيسي. خلاف ذلك أود أن أوصي باستخدام منشئ المناسب عند إنشاء المواضيع.

ولقد كتبت مقالة قصيرة عن هذا <وأ href = "http://www.thebestcsharpprogrammerintheworld.com/blogs/dynamic-foreach-forget-about-it-use-a-recursive-function٪20.aspx" يختلط = "نوفولو"> هنا . في الأساس، وأنا تمرير معلمة اختيارية يسمى، وعمق، مضيفا 1 إلى أنه في كل مرة أذهب أعمق في ذلك. ضمن أسلوب العودية أتحقق من العمق للقيمة. إذا كان أكبر من القيمة أنا وضعت، ورمي استثناء. ان قيمة (عتبة) أن يعتمد على احتياجات التطبيقات الخاصة بك.

وتذكر، إذا عليك أن تسأل عن حدود النظام، ثم انك ربما تفعل شيئا بشكل خاطئ.

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

وانها ليست صعبة لتحويل وظيفة عودي إلى واحدة متكررة، لا سيما وأن C # لديه جمع عام :: المكدس. باستخدام نوع المكدس يتحرك الذاكرة المستخدمة في كومة البرنامج بدلا من المكدس. وهذا يوفر لك مجموعة العنوان الكامل لتخزين البيانات متكررة. إذا كان هذا لا يكفي، فإنه ليس من الصعب جدا لصفحة البيانات إلى القرص. ولكن أود أن تنظر بجدية في حلول أخرى إذا كنت تحصل على هذه المرحلة.

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