PDA

View Full Version : ماکزیمم تعداد بازگشت در C#‎‎



mhfarzin
جمعه 07 شهریور 1393, 22:22 عصر
سلام خدمت همه دوستان
همانطور که میدونید حل بعضی از مسائل به کمک توابع بازگشتی خیلی راحت تره.
امروز با یکی از این مسائل برخورد داشتم. ولی مشکلی که وجود داره حداکثر تعداد بازگشت ها در دان نت گویا محدود است. مثلا کد ساده زیر رو در نظر بگیرید.


using System;

namespace Test
{
class Program
{
static void Main(string[] args)
{
recursive(0);
}

static void recursive(long Number)
{
Console.WriteLine(Number.ToString());
recursive(++Number);
}
}
}


این کد تو کامپیوتر من تا عدد 12189 رو چاپ میکنه و بعدش پیام StackOverflowException میده.
تو یه سایتی میخوندم دات نت فضای کمی برای استکش در نظر میگیره و این جور مواقع باید از Thread استفاده کنی و میتونی به عنوان دومین آرگومنتش میزان استک رو بدی. ولی اون هم باز محدودیت داره. یعنی عددی که به عنوان سایز استکش میگیره رو اگر زیاد وارد کنی همون شروع برنامه پیام StackOverflowException رو میده.
حالا برای مثال من یه تابع دارم که نیازه صد هزار بار خودش رو فراخوانی کنه تا به برگ برسه و تازه تو هر بار اجرا، خودش رو با چندین مقدار متفاوت فراخوانی میکنه(الگوریتم های بازگشت به عقب و شاخه و حد). راه حل این مشکل چیه؟

plus
جمعه 07 شهریور 1393, 23:01 عصر
اندازه Stack باید به همون روش ایجاد Thread قابل تنظیم باشه...خطای StackOverflowException ی که در این حالت دریافت میکنید ممکنه از جای دیگه باشه...آیا اندازه Stack رو به بایت به سازنده Thread میدین؟ چه مقداری میگذارین؟

mhfarzin
جمعه 07 شهریور 1393, 23:53 عصر
ورودیش یه عددی از نوع int هست. من سعی کردم بزرگترین عددی که ممکنه رو براش بزارم یعنی int.MaxValue


Thread Worker = new Thread(delegate() { recursive(0); }, int.MaxValue);


تو هیچ سایتی نتونستم پیدا کنم مقدار عددی که میگیره بر حسب چیه. مثلا بایت یا ...
حالا اگه جای int.MaxValue عدد کمتری بزارم کار میکنه مثلا 100000000 ولی مشکل اینه که تو این جا تعداد بازگشتش میره بالا ولی اگه مثلا یه مسئله باشه که بخوای تو هر بار اجرای تابع با چند تا مقدار متفاوت خودشو صدا بزنی باز هم خیلی زود پیام StackOverflowException رو میده.
یعنی کلا برام سوال شده اگه تعداد بازگشت تو یه مسئله سنگین بالا باشه راه حلش تو C#‎‎‎‎‎‎ چیه!!!!

plus
شنبه 08 شهریور 1393, 00:39 صبح
واحد بایت هست... شما int.MaxValue که میگذاری، میشه 2147483647 یعنی حدود 2 گیگابایت! خوب مشخصه که به مشکل بخوره...
مشکل چندان ربطی به #C نداره. به هر حال سیستم عامل یک محدودیتی رو برای StackSize در نظر میگیره حالا شما از هر زبانی استفاده کنی.مگه اینکه اون زبان روش دیگه ای رو برای پیاده سازی Stack استفاده کرده باشه...
حالا اگه شما حجم زیادی از اطلاعات رو در هر فراخوانی ارسال کنی طبیعتا طی اجرای این فراخوانی ها این مقادیر باید در حافظه نگه داشته باشن...در درجه اول باید بررسی کنید که حجم اینها حدودن چقدر هست.ممکنه این مقدار از کل حافظه قابل آدرسی دهی سیستم عامل هم بیشتر باشه! در این صورت حتی اگه موضوع Stack هم در میون نباشه مشکل باقی هست...
ولی اگه به این نتیجه رسیدید که مشکل از Stack هست، یک راه حل میتونه این باشه که شما تعداد آرگومان های متد رو به "یک" کاهش بدین و اون یک آرگومان هم، یک ارجاع به یک شئ هست که سایر آرگومان ها در اون شی هستن.
این آرگومان هم باید با استفاده از عملگر new روی Heap ایجاد بشن تا مشکل Stack نداشته باشید.
مثلا فرض کنید این متد شما هست:

void recursive(long number1, double number2, SomeStruct structValue)
{
// ...
recursive(newNumber1, newNumber2, newStructValue);
}

به این صورت عمل میکنید:

class RecursiveArguments {
long Number1 {
get;
set;
}
double Number2 {
get;
set;
}
SomeStruct StructValue {
get;
set;
}
}

void recursive(RecursiveArguments args) {
// ...
RecursiveArguments newArgs = new RecursiveArguments();
newArgs.Number1 = ...;
newArgs.Number2 = ...;
newArgs.StructValue = ...;
recursive(newArgs);
}

و در کل در متد Recursive تا حد ممکل از Stack استفاده نکنید.

mhfarzin
شنبه 08 شهریور 1393, 14:16 عصر
درسته تعداد آرگومانها رو باید کاهش داد تا حجم کمتری از استک اشغال شه.
ممنون از جواب کاملتون